PageRenderTime 47ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 1ms

lib/libc/net/getaddrinfo.c

http://www.minix3.org/
C | 1963 lines | 1488 code | 218 blank | 257 comment | 455 complexity | 3a03919862f758e0800a2cd05b2d13cd MD5 | raw file
Possible License(s): MIT, WTFPL, AGPL-1.0, BSD-3-Clause, GPL-3.0, LGPL-2.0, JSON, 0BSD
  1. /* $NetBSD: getaddrinfo.c,v 1.95 2009/10/02 07:41:08 wiz Exp $ */
  2. /* $KAME: getaddrinfo.c,v 1.29 2000/08/31 17:26:57 itojun Exp $ */
  3. /*
  4. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
  5. * 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 project 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 PROJECT 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 PROJECT 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. * Issues to be discussed:
  33. * - Return values. There are nonstandard return values defined and used
  34. * in the source code. This is because RFC2553 is silent about which error
  35. * code must be returned for which situation.
  36. * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2
  37. * says to use inet_aton() to convert IPv4 numeric to binary (alows
  38. * classful form as a result).
  39. * current code - disallow classful form for IPv4 (due to use of inet_pton).
  40. * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
  41. * invalid.
  42. * current code - SEGV on freeaddrinfo(NULL)
  43. * Note:
  44. * - The code filters out AFs that are not supported by the kernel,
  45. * when globbing NULL hostname (to loopback, or wildcard). Is it the right
  46. * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
  47. * in ai_flags?
  48. * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
  49. * (1) what should we do against numeric hostname (2) what should we do
  50. * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
  51. * non-loopback address configured? global address configured?
  52. */
  53. #include <sys/cdefs.h>
  54. #if defined(LIBC_SCCS) && !defined(lint)
  55. __RCSID("$NetBSD: getaddrinfo.c,v 1.95 2009/10/02 07:41:08 wiz Exp $");
  56. #endif /* LIBC_SCCS and not lint */
  57. #include "namespace.h"
  58. #include <sys/types.h>
  59. #include <sys/param.h>
  60. #include <sys/socket.h>
  61. #include <net/if.h>
  62. #include <netinet/in.h>
  63. #include <arpa/inet.h>
  64. #include <arpa/nameser.h>
  65. #include <assert.h>
  66. #include <ctype.h>
  67. #include <errno.h>
  68. #include <netdb.h>
  69. #include <resolv.h>
  70. #include <stddef.h>
  71. #include <stdio.h>
  72. #include <stdlib.h>
  73. #include <string.h>
  74. #include <unistd.h>
  75. #include <syslog.h>
  76. #include <stdarg.h>
  77. #include <nsswitch.h>
  78. #ifdef YP
  79. #include <rpc/rpc.h>
  80. #include <rpcsvc/yp_prot.h>
  81. #include <rpcsvc/ypclnt.h>
  82. #endif
  83. #include "servent.h"
  84. #ifdef __weak_alias
  85. __weak_alias(getaddrinfo,_getaddrinfo)
  86. __weak_alias(freeaddrinfo,_freeaddrinfo)
  87. __weak_alias(gai_strerror,_gai_strerror)
  88. #endif
  89. #define SUCCESS 0
  90. #define ANY 0
  91. #define YES 1
  92. #define NO 0
  93. static const char in_addrany[] = { 0, 0, 0, 0 };
  94. static const char in_loopback[] = { 127, 0, 0, 1 };
  95. #ifdef INET6
  96. static const char in6_addrany[] = {
  97. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  98. };
  99. static const char in6_loopback[] = {
  100. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
  101. };
  102. #endif
  103. static const struct afd {
  104. int a_af;
  105. int a_addrlen;
  106. int a_socklen;
  107. int a_off;
  108. const char *a_addrany;
  109. const char *a_loopback;
  110. int a_scoped;
  111. } afdl [] = {
  112. #ifdef INET6
  113. {PF_INET6, sizeof(struct in6_addr),
  114. sizeof(struct sockaddr_in6),
  115. offsetof(struct sockaddr_in6, sin6_addr),
  116. in6_addrany, in6_loopback, 1},
  117. #endif
  118. {PF_INET, sizeof(struct in_addr),
  119. sizeof(struct sockaddr_in),
  120. offsetof(struct sockaddr_in, sin_addr),
  121. in_addrany, in_loopback, 0},
  122. {0, 0, 0, 0, NULL, NULL, 0},
  123. };
  124. struct explore {
  125. int e_af;
  126. int e_socktype;
  127. int e_protocol;
  128. const char *e_protostr;
  129. int e_wild;
  130. #define WILD_AF(ex) ((ex)->e_wild & 0x01)
  131. #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
  132. #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
  133. };
  134. static const struct explore explore[] = {
  135. #if 0
  136. { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
  137. #endif
  138. #ifdef INET6
  139. { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
  140. { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
  141. { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
  142. #endif
  143. { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
  144. { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
  145. { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
  146. { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
  147. { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
  148. { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
  149. { -1, 0, 0, NULL, 0 },
  150. };
  151. #ifdef INET6
  152. #define PTON_MAX 16
  153. #else
  154. #define PTON_MAX 4
  155. #endif
  156. static const ns_src default_dns_files[] = {
  157. { NSSRC_FILES, NS_SUCCESS },
  158. { NSSRC_DNS, NS_SUCCESS },
  159. { 0, 0 }
  160. };
  161. #define MAXPACKET (64*1024)
  162. typedef union {
  163. HEADER hdr;
  164. u_char buf[MAXPACKET];
  165. } querybuf;
  166. struct res_target {
  167. struct res_target *next;
  168. const char *name; /* domain name */
  169. int qclass, qtype; /* class and type of query */
  170. u_char *answer; /* buffer to put answer */
  171. int anslen; /* size of answer buffer */
  172. int n; /* result length */
  173. };
  174. static int str2number(const char *);
  175. static int explore_fqdn(const struct addrinfo *, const char *,
  176. const char *, struct addrinfo **, struct servent_data *);
  177. static int explore_null(const struct addrinfo *,
  178. const char *, struct addrinfo **, struct servent_data *);
  179. static int explore_numeric(const struct addrinfo *, const char *,
  180. const char *, struct addrinfo **, const char *, struct servent_data *);
  181. static int explore_numeric_scope(const struct addrinfo *, const char *,
  182. const char *, struct addrinfo **, struct servent_data *);
  183. static int get_canonname(const struct addrinfo *,
  184. struct addrinfo *, const char *);
  185. static struct addrinfo *get_ai(const struct addrinfo *,
  186. const struct afd *, const char *);
  187. static int get_portmatch(const struct addrinfo *, const char *,
  188. struct servent_data *);
  189. static int get_port(const struct addrinfo *, const char *, int,
  190. struct servent_data *);
  191. static const struct afd *find_afd(int);
  192. #ifdef INET6
  193. static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
  194. #endif
  195. static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
  196. const struct addrinfo *);
  197. static void aisort(struct addrinfo *s, res_state res);
  198. static int _dns_getaddrinfo(void *, void *, va_list);
  199. static void _sethtent(FILE **);
  200. static void _endhtent(FILE **);
  201. static struct addrinfo *_gethtent(FILE **, const char *,
  202. const struct addrinfo *);
  203. static int _files_getaddrinfo(void *, void *, va_list);
  204. #ifdef YP
  205. static struct addrinfo *_yphostent(char *, const struct addrinfo *);
  206. static int _yp_getaddrinfo(void *, void *, va_list);
  207. #endif
  208. static int res_queryN(const char *, struct res_target *, res_state);
  209. static int res_searchN(const char *, struct res_target *, res_state);
  210. static int res_querydomainN(const char *, const char *,
  211. struct res_target *, res_state);
  212. static const char * const ai_errlist[] = {
  213. "Success",
  214. "Address family for hostname not supported", /* EAI_ADDRFAMILY */
  215. "Temporary failure in name resolution", /* EAI_AGAIN */
  216. "Invalid value for ai_flags", /* EAI_BADFLAGS */
  217. "Non-recoverable failure in name resolution", /* EAI_FAIL */
  218. "ai_family not supported", /* EAI_FAMILY */
  219. "Memory allocation failure", /* EAI_MEMORY */
  220. "No address associated with hostname", /* EAI_NODATA */
  221. "hostname nor servname provided, or not known", /* EAI_NONAME */
  222. "servname not supported for ai_socktype", /* EAI_SERVICE */
  223. "ai_socktype not supported", /* EAI_SOCKTYPE */
  224. "System error returned in errno", /* EAI_SYSTEM */
  225. "Invalid value for hints", /* EAI_BADHINTS */
  226. "Resolved protocol is unknown", /* EAI_PROTOCOL */
  227. "Argument buffer overflow", /* EAI_OVERFLOW */
  228. "Unknown error", /* EAI_MAX */
  229. };
  230. /* XXX macros that make external reference is BAD. */
  231. #define GET_AI(ai, afd, addr) \
  232. do { \
  233. /* external reference: pai, error, and label free */ \
  234. (ai) = get_ai(pai, (afd), (addr)); \
  235. if ((ai) == NULL) { \
  236. error = EAI_MEMORY; \
  237. goto free; \
  238. } \
  239. } while (/*CONSTCOND*/0)
  240. #define GET_PORT(ai, serv, svd) \
  241. do { \
  242. /* external reference: error and label free */ \
  243. error = get_port((ai), (serv), 0, (svd)); \
  244. if (error != 0) \
  245. goto free; \
  246. } while (/*CONSTCOND*/0)
  247. #define GET_CANONNAME(ai, str) \
  248. do { \
  249. /* external reference: pai, error and label free */ \
  250. error = get_canonname(pai, (ai), (str)); \
  251. if (error != 0) \
  252. goto free; \
  253. } while (/*CONSTCOND*/0)
  254. #define ERR(err) \
  255. do { \
  256. /* external reference: error, and label bad */ \
  257. error = (err); \
  258. goto bad; \
  259. /*NOTREACHED*/ \
  260. } while (/*CONSTCOND*/0)
  261. #define MATCH_FAMILY(x, y, w) \
  262. ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || \
  263. (y) == PF_UNSPEC)))
  264. #define MATCH(x, y, w) \
  265. ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
  266. const char *
  267. gai_strerror(int ecode)
  268. {
  269. if (ecode < 0 || ecode > EAI_MAX)
  270. ecode = EAI_MAX;
  271. return ai_errlist[ecode];
  272. }
  273. void
  274. freeaddrinfo(struct addrinfo *ai)
  275. {
  276. struct addrinfo *next;
  277. _DIAGASSERT(ai != NULL);
  278. do {
  279. next = ai->ai_next;
  280. if (ai->ai_canonname)
  281. free(ai->ai_canonname);
  282. /* no need to free(ai->ai_addr) */
  283. free(ai);
  284. ai = next;
  285. } while (ai);
  286. }
  287. static int
  288. str2number(const char *p)
  289. {
  290. char *ep;
  291. unsigned long v;
  292. _DIAGASSERT(p != NULL);
  293. if (*p == '\0')
  294. return -1;
  295. ep = NULL;
  296. errno = 0;
  297. v = strtoul(p, &ep, 10);
  298. if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX)
  299. return v;
  300. else
  301. return -1;
  302. }
  303. int
  304. getaddrinfo(const char *hostname, const char *servname,
  305. const struct addrinfo *hints, struct addrinfo **res)
  306. {
  307. struct addrinfo sentinel;
  308. struct addrinfo *cur;
  309. int error = 0;
  310. struct addrinfo ai;
  311. struct addrinfo ai0;
  312. struct addrinfo *pai;
  313. const struct explore *ex;
  314. struct servent_data svd;
  315. /* hostname is allowed to be NULL */
  316. /* servname is allowed to be NULL */
  317. /* hints is allowed to be NULL */
  318. _DIAGASSERT(res != NULL);
  319. (void)memset(&svd, 0, sizeof(svd));
  320. memset(&sentinel, 0, sizeof(sentinel));
  321. cur = &sentinel;
  322. memset(&ai, 0, sizeof(ai));
  323. pai = &ai;
  324. pai->ai_flags = 0;
  325. pai->ai_family = PF_UNSPEC;
  326. pai->ai_socktype = ANY;
  327. pai->ai_protocol = ANY;
  328. pai->ai_addrlen = 0;
  329. pai->ai_canonname = NULL;
  330. pai->ai_addr = NULL;
  331. pai->ai_next = NULL;
  332. if (hostname == NULL && servname == NULL)
  333. return EAI_NONAME;
  334. if (hints) {
  335. /* error check for hints */
  336. if (hints->ai_addrlen || hints->ai_canonname ||
  337. hints->ai_addr || hints->ai_next)
  338. ERR(EAI_BADHINTS); /* xxx */
  339. if (hints->ai_flags & ~AI_MASK)
  340. ERR(EAI_BADFLAGS);
  341. switch (hints->ai_family) {
  342. case PF_UNSPEC:
  343. case PF_INET:
  344. #ifdef INET6
  345. case PF_INET6:
  346. #endif
  347. break;
  348. default:
  349. ERR(EAI_FAMILY);
  350. }
  351. memcpy(pai, hints, sizeof(*pai));
  352. /*
  353. * if both socktype/protocol are specified, check if they
  354. * are meaningful combination.
  355. */
  356. if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
  357. for (ex = explore; ex->e_af >= 0; ex++) {
  358. if (pai->ai_family != ex->e_af)
  359. continue;
  360. if (ex->e_socktype == ANY)
  361. continue;
  362. if (ex->e_protocol == ANY)
  363. continue;
  364. if (pai->ai_socktype == ex->e_socktype
  365. && pai->ai_protocol != ex->e_protocol) {
  366. ERR(EAI_BADHINTS);
  367. }
  368. }
  369. }
  370. }
  371. /*
  372. * check for special cases. (1) numeric servname is disallowed if
  373. * socktype/protocol are left unspecified. (2) servname is disallowed
  374. * for raw and other inet{,6} sockets.
  375. */
  376. if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
  377. #ifdef PF_INET6
  378. || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
  379. #endif
  380. ) {
  381. ai0 = *pai; /* backup *pai */
  382. if (pai->ai_family == PF_UNSPEC) {
  383. #ifdef PF_INET6
  384. pai->ai_family = PF_INET6;
  385. #else
  386. pai->ai_family = PF_INET;
  387. #endif
  388. }
  389. error = get_portmatch(pai, servname, &svd);
  390. if (error)
  391. ERR(error);
  392. *pai = ai0;
  393. }
  394. ai0 = *pai;
  395. /* NULL hostname, or numeric hostname */
  396. for (ex = explore; ex->e_af >= 0; ex++) {
  397. *pai = ai0;
  398. /* PF_UNSPEC entries are prepared for DNS queries only */
  399. if (ex->e_af == PF_UNSPEC)
  400. continue;
  401. if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
  402. continue;
  403. if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
  404. continue;
  405. if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
  406. continue;
  407. if (pai->ai_family == PF_UNSPEC)
  408. pai->ai_family = ex->e_af;
  409. if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
  410. pai->ai_socktype = ex->e_socktype;
  411. if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
  412. pai->ai_protocol = ex->e_protocol;
  413. if (hostname == NULL)
  414. error = explore_null(pai, servname, &cur->ai_next,
  415. &svd);
  416. else
  417. error = explore_numeric_scope(pai, hostname, servname,
  418. &cur->ai_next, &svd);
  419. if (error)
  420. goto free;
  421. while (cur->ai_next)
  422. cur = cur->ai_next;
  423. }
  424. /*
  425. * XXX
  426. * If numeric representation of AF1 can be interpreted as FQDN
  427. * representation of AF2, we need to think again about the code below.
  428. */
  429. if (sentinel.ai_next)
  430. goto good;
  431. if (hostname == NULL)
  432. ERR(EAI_NODATA);
  433. if (pai->ai_flags & AI_NUMERICHOST)
  434. ERR(EAI_NONAME);
  435. /*
  436. * hostname as alphabetical name.
  437. * we would like to prefer AF_INET6 than AF_INET, so we'll make a
  438. * outer loop by AFs.
  439. */
  440. for (ex = explore; ex->e_af >= 0; ex++) {
  441. *pai = ai0;
  442. /* require exact match for family field */
  443. if (pai->ai_family != ex->e_af)
  444. continue;
  445. if (!MATCH(pai->ai_socktype, ex->e_socktype,
  446. WILD_SOCKTYPE(ex))) {
  447. continue;
  448. }
  449. if (!MATCH(pai->ai_protocol, ex->e_protocol,
  450. WILD_PROTOCOL(ex))) {
  451. continue;
  452. }
  453. if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
  454. pai->ai_socktype = ex->e_socktype;
  455. if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
  456. pai->ai_protocol = ex->e_protocol;
  457. error = explore_fqdn(pai, hostname, servname, &cur->ai_next,
  458. &svd);
  459. while (cur && cur->ai_next)
  460. cur = cur->ai_next;
  461. }
  462. /* XXX */
  463. if (sentinel.ai_next)
  464. error = 0;
  465. if (error)
  466. goto free;
  467. if (sentinel.ai_next) {
  468. good:
  469. endservent_r(&svd);
  470. *res = sentinel.ai_next;
  471. return SUCCESS;
  472. } else
  473. error = EAI_FAIL;
  474. free:
  475. bad:
  476. endservent_r(&svd);
  477. if (sentinel.ai_next)
  478. freeaddrinfo(sentinel.ai_next);
  479. *res = NULL;
  480. return error;
  481. }
  482. /*
  483. * FQDN hostname, DNS lookup
  484. */
  485. static int
  486. explore_fqdn(const struct addrinfo *pai, const char *hostname,
  487. const char *servname, struct addrinfo **res, struct servent_data *svd)
  488. {
  489. struct addrinfo *result;
  490. struct addrinfo *cur;
  491. int error = 0;
  492. static const ns_dtab dtab[] = {
  493. NS_FILES_CB(_files_getaddrinfo, NULL)
  494. { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */
  495. NS_NIS_CB(_yp_getaddrinfo, NULL)
  496. NS_NULL_CB
  497. };
  498. _DIAGASSERT(pai != NULL);
  499. /* hostname may be NULL */
  500. /* servname may be NULL */
  501. _DIAGASSERT(res != NULL);
  502. result = NULL;
  503. /*
  504. * if the servname does not match socktype/protocol, ignore it.
  505. */
  506. if (get_portmatch(pai, servname, svd) != 0)
  507. return 0;
  508. switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
  509. default_dns_files, hostname, pai)) {
  510. case NS_TRYAGAIN:
  511. error = EAI_AGAIN;
  512. goto free;
  513. case NS_UNAVAIL:
  514. error = EAI_FAIL;
  515. goto free;
  516. case NS_NOTFOUND:
  517. error = EAI_NODATA;
  518. goto free;
  519. case NS_SUCCESS:
  520. error = 0;
  521. for (cur = result; cur; cur = cur->ai_next) {
  522. GET_PORT(cur, servname, svd);
  523. /* canonname should be filled already */
  524. }
  525. break;
  526. }
  527. *res = result;
  528. return 0;
  529. free:
  530. if (result)
  531. freeaddrinfo(result);
  532. return error;
  533. }
  534. /*
  535. * hostname == NULL.
  536. * passive socket -> anyaddr (0.0.0.0 or ::)
  537. * non-passive socket -> localhost (127.0.0.1 or ::1)
  538. */
  539. static int
  540. explore_null(const struct addrinfo *pai, const char *servname,
  541. struct addrinfo **res, struct servent_data *svd)
  542. {
  543. int s;
  544. const struct afd *afd;
  545. struct addrinfo *cur;
  546. struct addrinfo sentinel;
  547. int error;
  548. _DIAGASSERT(pai != NULL);
  549. /* servname may be NULL */
  550. _DIAGASSERT(res != NULL);
  551. *res = NULL;
  552. sentinel.ai_next = NULL;
  553. cur = &sentinel;
  554. /*
  555. * filter out AFs that are not supported by the kernel
  556. * XXX errno?
  557. */
  558. s = socket(pai->ai_family, SOCK_DGRAM, 0);
  559. if (s < 0) {
  560. if (errno != EMFILE)
  561. return 0;
  562. } else
  563. close(s);
  564. /*
  565. * if the servname does not match socktype/protocol, ignore it.
  566. */
  567. if (get_portmatch(pai, servname, svd) != 0)
  568. return 0;
  569. afd = find_afd(pai->ai_family);
  570. if (afd == NULL)
  571. return 0;
  572. if (pai->ai_flags & AI_PASSIVE) {
  573. GET_AI(cur->ai_next, afd, afd->a_addrany);
  574. /* xxx meaningless?
  575. * GET_CANONNAME(cur->ai_next, "anyaddr");
  576. */
  577. GET_PORT(cur->ai_next, servname, svd);
  578. } else {
  579. GET_AI(cur->ai_next, afd, afd->a_loopback);
  580. /* xxx meaningless?
  581. * GET_CANONNAME(cur->ai_next, "localhost");
  582. */
  583. GET_PORT(cur->ai_next, servname, svd);
  584. }
  585. cur = cur->ai_next;
  586. *res = sentinel.ai_next;
  587. return 0;
  588. free:
  589. if (sentinel.ai_next)
  590. freeaddrinfo(sentinel.ai_next);
  591. return error;
  592. }
  593. /*
  594. * numeric hostname
  595. */
  596. static int
  597. explore_numeric(const struct addrinfo *pai, const char *hostname,
  598. const char *servname, struct addrinfo **res, const char *canonname,
  599. struct servent_data *svd)
  600. {
  601. const struct afd *afd;
  602. struct addrinfo *cur;
  603. struct addrinfo sentinel;
  604. int error;
  605. char pton[PTON_MAX];
  606. _DIAGASSERT(pai != NULL);
  607. /* hostname may be NULL */
  608. /* servname may be NULL */
  609. _DIAGASSERT(res != NULL);
  610. *res = NULL;
  611. sentinel.ai_next = NULL;
  612. cur = &sentinel;
  613. /*
  614. * if the servname does not match socktype/protocol, ignore it.
  615. */
  616. if (get_portmatch(pai, servname, svd) != 0)
  617. return 0;
  618. afd = find_afd(pai->ai_family);
  619. if (afd == NULL)
  620. return 0;
  621. switch (afd->a_af) {
  622. #if 0 /*X/Open spec*/
  623. case AF_INET:
  624. if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
  625. if (pai->ai_family == afd->a_af ||
  626. pai->ai_family == PF_UNSPEC /*?*/) {
  627. GET_AI(cur->ai_next, afd, pton);
  628. GET_PORT(cur->ai_next, servname, svd);
  629. if ((pai->ai_flags & AI_CANONNAME)) {
  630. /*
  631. * Set the numeric address itself as
  632. * the canonical name, based on a
  633. * clarification in rfc2553bis-03.
  634. */
  635. GET_CANONNAME(cur->ai_next, canonname);
  636. }
  637. while (cur && cur->ai_next)
  638. cur = cur->ai_next;
  639. } else
  640. ERR(EAI_FAMILY); /*xxx*/
  641. }
  642. break;
  643. #endif
  644. default:
  645. if (inet_pton(afd->a_af, hostname, pton) == 1) {
  646. if (pai->ai_family == afd->a_af ||
  647. pai->ai_family == PF_UNSPEC /*?*/) {
  648. GET_AI(cur->ai_next, afd, pton);
  649. GET_PORT(cur->ai_next, servname, svd);
  650. if ((pai->ai_flags & AI_CANONNAME)) {
  651. /*
  652. * Set the numeric address itself as
  653. * the canonical name, based on a
  654. * clarification in rfc2553bis-03.
  655. */
  656. GET_CANONNAME(cur->ai_next, canonname);
  657. }
  658. while (cur->ai_next)
  659. cur = cur->ai_next;
  660. } else
  661. ERR(EAI_FAMILY); /*xxx*/
  662. }
  663. break;
  664. }
  665. *res = sentinel.ai_next;
  666. return 0;
  667. free:
  668. bad:
  669. if (sentinel.ai_next)
  670. freeaddrinfo(sentinel.ai_next);
  671. return error;
  672. }
  673. /*
  674. * numeric hostname with scope
  675. */
  676. static int
  677. explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
  678. const char *servname, struct addrinfo **res, struct servent_data *svd)
  679. {
  680. #if !defined(SCOPE_DELIMITER) || !defined(INET6)
  681. return explore_numeric(pai, hostname, servname, res, hostname, svd);
  682. #else
  683. const struct afd *afd;
  684. struct addrinfo *cur;
  685. int error;
  686. char *cp, *hostname2 = NULL, *scope, *addr;
  687. struct sockaddr_in6 *sin6;
  688. _DIAGASSERT(pai != NULL);
  689. /* hostname may be NULL */
  690. /* servname may be NULL */
  691. _DIAGASSERT(res != NULL);
  692. /*
  693. * if the servname does not match socktype/protocol, ignore it.
  694. */
  695. if (get_portmatch(pai, servname, svd) != 0)
  696. return 0;
  697. afd = find_afd(pai->ai_family);
  698. if (afd == NULL)
  699. return 0;
  700. if (!afd->a_scoped)
  701. return explore_numeric(pai, hostname, servname, res, hostname,
  702. svd);
  703. cp = strchr(hostname, SCOPE_DELIMITER);
  704. if (cp == NULL)
  705. return explore_numeric(pai, hostname, servname, res, hostname,
  706. svd);
  707. /*
  708. * Handle special case of <scoped_address><delimiter><scope id>
  709. */
  710. hostname2 = strdup(hostname);
  711. if (hostname2 == NULL)
  712. return EAI_MEMORY;
  713. /* terminate at the delimiter */
  714. hostname2[cp - hostname] = '\0';
  715. addr = hostname2;
  716. scope = cp + 1;
  717. error = explore_numeric(pai, addr, servname, res, hostname, svd);
  718. if (error == 0) {
  719. u_int32_t scopeid;
  720. for (cur = *res; cur; cur = cur->ai_next) {
  721. if (cur->ai_family != AF_INET6)
  722. continue;
  723. sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
  724. if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
  725. free(hostname2);
  726. return(EAI_NODATA); /* XXX: is return OK? */
  727. }
  728. sin6->sin6_scope_id = scopeid;
  729. }
  730. }
  731. free(hostname2);
  732. return error;
  733. #endif
  734. }
  735. static int
  736. get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
  737. {
  738. _DIAGASSERT(pai != NULL);
  739. _DIAGASSERT(ai != NULL);
  740. _DIAGASSERT(str != NULL);
  741. if ((pai->ai_flags & AI_CANONNAME) != 0) {
  742. ai->ai_canonname = strdup(str);
  743. if (ai->ai_canonname == NULL)
  744. return EAI_MEMORY;
  745. }
  746. return 0;
  747. }
  748. struct addrinfo *
  749. allocaddrinfo(socklen_t addrlen)
  750. {
  751. struct addrinfo *ai;
  752. ai = calloc(sizeof(struct addrinfo) + addrlen, 1);
  753. if (ai) {
  754. ai->ai_addr = (void *)(ai+1);
  755. #ifndef __minix
  756. ai->ai_addrlen = ai->ai_addr->sa_len = addrlen;
  757. #else /* __minix */
  758. ai->ai_addrlen = addrlen;
  759. #endif
  760. }
  761. return ai;
  762. }
  763. static struct addrinfo *
  764. get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
  765. {
  766. char *p;
  767. struct addrinfo *ai;
  768. struct sockaddr *save;
  769. _DIAGASSERT(pai != NULL);
  770. _DIAGASSERT(afd != NULL);
  771. _DIAGASSERT(addr != NULL);
  772. ai = allocaddrinfo((socklen_t)afd->a_socklen);
  773. if (ai == NULL)
  774. return NULL;
  775. save = ai->ai_addr;
  776. memcpy(ai, pai, sizeof(struct addrinfo));
  777. /* since we just overwrote all of ai, we have
  778. to restore ai_addr and ai_addrlen */
  779. ai->ai_addr = save;
  780. ai->ai_addrlen = (socklen_t)afd->a_socklen;
  781. ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
  782. p = (char *)(void *)(ai->ai_addr);
  783. memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
  784. return ai;
  785. }
  786. static int
  787. get_portmatch(const struct addrinfo *ai, const char *servname,
  788. struct servent_data *svd)
  789. {
  790. _DIAGASSERT(ai != NULL);
  791. /* servname may be NULL */
  792. return get_port(ai, servname, 1, svd);
  793. }
  794. static int
  795. get_port(const struct addrinfo *ai, const char *servname, int matchonly,
  796. struct servent_data *svd)
  797. {
  798. const char *proto;
  799. struct servent *sp;
  800. int port;
  801. int allownumeric;
  802. _DIAGASSERT(ai != NULL);
  803. /* servname may be NULL */
  804. if (servname == NULL)
  805. return 0;
  806. switch (ai->ai_family) {
  807. case AF_INET:
  808. #ifdef AF_INET6
  809. case AF_INET6:
  810. #endif
  811. break;
  812. default:
  813. return 0;
  814. }
  815. switch (ai->ai_socktype) {
  816. case SOCK_RAW:
  817. return EAI_SERVICE;
  818. case SOCK_DGRAM:
  819. case SOCK_STREAM:
  820. allownumeric = 1;
  821. break;
  822. case ANY:
  823. /*
  824. * This was 0. It is now 1 so that queries specifying
  825. * a NULL hint, or hint without socktype (but, hopefully,
  826. * with protocol) and numeric address actually work.
  827. */
  828. allownumeric = 1;
  829. break;
  830. default:
  831. return EAI_SOCKTYPE;
  832. }
  833. port = str2number(servname);
  834. if (port >= 0) {
  835. if (!allownumeric)
  836. return EAI_SERVICE;
  837. if (port < 0 || port > 65535)
  838. return EAI_SERVICE;
  839. port = htons(port);
  840. } else {
  841. struct servent sv;
  842. if (ai->ai_flags & AI_NUMERICSERV)
  843. return EAI_NONAME;
  844. switch (ai->ai_socktype) {
  845. case SOCK_DGRAM:
  846. proto = "udp";
  847. break;
  848. case SOCK_STREAM:
  849. proto = "tcp";
  850. break;
  851. default:
  852. proto = NULL;
  853. break;
  854. }
  855. sp = getservbyname_r(servname, proto, &sv, svd);
  856. if (sp == NULL)
  857. return EAI_SERVICE;
  858. port = sp->s_port;
  859. }
  860. if (!matchonly) {
  861. switch (ai->ai_family) {
  862. case AF_INET:
  863. ((struct sockaddr_in *)(void *)
  864. ai->ai_addr)->sin_port = port;
  865. break;
  866. #ifdef INET6
  867. case AF_INET6:
  868. ((struct sockaddr_in6 *)(void *)
  869. ai->ai_addr)->sin6_port = port;
  870. break;
  871. #endif
  872. }
  873. }
  874. return 0;
  875. }
  876. static const struct afd *
  877. find_afd(int af)
  878. {
  879. const struct afd *afd;
  880. if (af == PF_UNSPEC)
  881. return NULL;
  882. for (afd = afdl; afd->a_af; afd++) {
  883. if (afd->a_af == af)
  884. return afd;
  885. }
  886. return NULL;
  887. }
  888. #ifdef INET6
  889. /* convert a string to a scope identifier. XXX: IPv6 specific */
  890. static int
  891. ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
  892. {
  893. u_long lscopeid;
  894. struct in6_addr *a6;
  895. char *ep;
  896. _DIAGASSERT(scope != NULL);
  897. _DIAGASSERT(sin6 != NULL);
  898. _DIAGASSERT(scopeid != NULL);
  899. a6 = &sin6->sin6_addr;
  900. /* empty scopeid portion is invalid */
  901. if (*scope == '\0')
  902. return -1;
  903. if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
  904. /*
  905. * We currently assume a one-to-one mapping between links
  906. * and interfaces, so we simply use interface indices for
  907. * like-local scopes.
  908. */
  909. *scopeid = if_nametoindex(scope);
  910. if (*scopeid == 0)
  911. goto trynumeric;
  912. return 0;
  913. }
  914. /* still unclear about literal, allow numeric only - placeholder */
  915. if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
  916. goto trynumeric;
  917. if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
  918. goto trynumeric;
  919. else
  920. goto trynumeric; /* global */
  921. /* try to convert to a numeric id as a last resort */
  922. trynumeric:
  923. errno = 0;
  924. lscopeid = strtoul(scope, &ep, 10);
  925. *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
  926. if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
  927. return 0;
  928. else
  929. return -1;
  930. }
  931. #endif
  932. /* code duplicate with gethnamaddr.c */
  933. static const char AskedForGot[] =
  934. "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
  935. static struct addrinfo *
  936. getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
  937. const struct addrinfo *pai)
  938. {
  939. struct addrinfo sentinel, *cur;
  940. struct addrinfo ai;
  941. const struct afd *afd;
  942. char *canonname;
  943. const HEADER *hp;
  944. const u_char *cp;
  945. int n;
  946. const u_char *eom;
  947. char *bp, *ep;
  948. int type, class, ancount, qdcount;
  949. int haveanswer, had_error;
  950. char tbuf[MAXDNAME];
  951. int (*name_ok) (const char *);
  952. char hostbuf[8*1024];
  953. _DIAGASSERT(answer != NULL);
  954. _DIAGASSERT(qname != NULL);
  955. _DIAGASSERT(pai != NULL);
  956. memset(&sentinel, 0, sizeof(sentinel));
  957. cur = &sentinel;
  958. canonname = NULL;
  959. eom = answer->buf + anslen;
  960. switch (qtype) {
  961. case T_A:
  962. case T_AAAA:
  963. case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
  964. name_ok = res_hnok;
  965. break;
  966. default:
  967. return NULL; /* XXX should be abort(); */
  968. }
  969. /*
  970. * find first satisfactory answer
  971. */
  972. hp = &answer->hdr;
  973. ancount = ntohs(hp->ancount);
  974. qdcount = ntohs(hp->qdcount);
  975. bp = hostbuf;
  976. ep = hostbuf + sizeof hostbuf;
  977. cp = answer->buf + HFIXEDSZ;
  978. if (qdcount != 1) {
  979. h_errno = NO_RECOVERY;
  980. return (NULL);
  981. }
  982. n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
  983. if ((n < 0) || !(*name_ok)(bp)) {
  984. h_errno = NO_RECOVERY;
  985. return (NULL);
  986. }
  987. cp += n + QFIXEDSZ;
  988. if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
  989. /* res_send() has already verified that the query name is the
  990. * same as the one we sent; this just gets the expanded name
  991. * (i.e., with the succeeding search-domain tacked on).
  992. */
  993. n = strlen(bp) + 1; /* for the \0 */
  994. if (n >= MAXHOSTNAMELEN) {
  995. h_errno = NO_RECOVERY;
  996. return (NULL);
  997. }
  998. canonname = bp;
  999. bp += n;
  1000. /* The qname can be abbreviated, but h_name is now absolute. */
  1001. qname = canonname;
  1002. }
  1003. haveanswer = 0;
  1004. had_error = 0;
  1005. while (ancount-- > 0 && cp < eom && !had_error) {
  1006. n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
  1007. if ((n < 0) || !(*name_ok)(bp)) {
  1008. had_error++;
  1009. continue;
  1010. }
  1011. cp += n; /* name */
  1012. type = _getshort(cp);
  1013. cp += INT16SZ; /* type */
  1014. class = _getshort(cp);
  1015. cp += INT16SZ + INT32SZ; /* class, TTL */
  1016. n = _getshort(cp);
  1017. cp += INT16SZ; /* len */
  1018. if (class != C_IN) {
  1019. /* XXX - debug? syslog? */
  1020. cp += n;
  1021. continue; /* XXX - had_error++ ? */
  1022. }
  1023. if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
  1024. type == T_CNAME) {
  1025. n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
  1026. if ((n < 0) || !(*name_ok)(tbuf)) {
  1027. had_error++;
  1028. continue;
  1029. }
  1030. cp += n;
  1031. /* Get canonical name. */
  1032. n = strlen(tbuf) + 1; /* for the \0 */
  1033. if (n > ep - bp || n >= MAXHOSTNAMELEN) {
  1034. had_error++;
  1035. continue;
  1036. }
  1037. strlcpy(bp, tbuf, (size_t)(ep - bp));
  1038. canonname = bp;
  1039. bp += n;
  1040. continue;
  1041. }
  1042. if (qtype == T_ANY) {
  1043. if (!(type == T_A || type == T_AAAA)) {
  1044. cp += n;
  1045. continue;
  1046. }
  1047. } else if (type != qtype) {
  1048. if (type != T_KEY && type != T_SIG) {
  1049. struct syslog_data sd = SYSLOG_DATA_INIT;
  1050. syslog_r(LOG_NOTICE|LOG_AUTH, &sd,
  1051. "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
  1052. qname, p_class(C_IN), p_type(qtype),
  1053. p_type(type));
  1054. }
  1055. cp += n;
  1056. continue; /* XXX - had_error++ ? */
  1057. }
  1058. switch (type) {
  1059. case T_A:
  1060. case T_AAAA:
  1061. if (strcasecmp(canonname, bp) != 0) {
  1062. struct syslog_data sd = SYSLOG_DATA_INIT;
  1063. syslog_r(LOG_NOTICE|LOG_AUTH, &sd,
  1064. AskedForGot, canonname, bp);
  1065. cp += n;
  1066. continue; /* XXX - had_error++ ? */
  1067. }
  1068. if (type == T_A && n != INADDRSZ) {
  1069. cp += n;
  1070. continue;
  1071. }
  1072. if (type == T_AAAA && n != IN6ADDRSZ) {
  1073. cp += n;
  1074. continue;
  1075. }
  1076. if (type == T_AAAA) {
  1077. struct in6_addr in6;
  1078. memcpy(&in6, cp, IN6ADDRSZ);
  1079. if (IN6_IS_ADDR_V4MAPPED(&in6)) {
  1080. cp += n;
  1081. continue;
  1082. }
  1083. }
  1084. if (!haveanswer) {
  1085. int nn;
  1086. canonname = bp;
  1087. nn = strlen(bp) + 1; /* for the \0 */
  1088. bp += nn;
  1089. }
  1090. /* don't overwrite pai */
  1091. ai = *pai;
  1092. ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
  1093. afd = find_afd(ai.ai_family);
  1094. if (afd == NULL) {
  1095. cp += n;
  1096. continue;
  1097. }
  1098. cur->ai_next = get_ai(&ai, afd, (const char *)cp);
  1099. if (cur->ai_next == NULL)
  1100. had_error++;
  1101. while (cur && cur->ai_next)
  1102. cur = cur->ai_next;
  1103. cp += n;
  1104. break;
  1105. default:
  1106. abort();
  1107. }
  1108. if (!had_error)
  1109. haveanswer++;
  1110. }
  1111. if (haveanswer) {
  1112. if (!canonname)
  1113. (void)get_canonname(pai, sentinel.ai_next, qname);
  1114. else
  1115. (void)get_canonname(pai, sentinel.ai_next, canonname);
  1116. h_errno = NETDB_SUCCESS;
  1117. return sentinel.ai_next;
  1118. }
  1119. h_errno = NO_RECOVERY;
  1120. return NULL;
  1121. }
  1122. #define SORTEDADDR(p) (((struct sockaddr_in *)(void *)(p->ai_next->ai_addr))->sin_addr.s_addr)
  1123. #define SORTMATCH(p, s) ((SORTEDADDR(p) & (s).mask) == (s).addr.s_addr)
  1124. static void
  1125. aisort(struct addrinfo *s, res_state res)
  1126. {
  1127. struct addrinfo head, *t, *p;
  1128. int i;
  1129. head.ai_next = NULL;
  1130. t = &head;
  1131. for (i = 0; i < res->nsort; i++) {
  1132. p = s;
  1133. while (p->ai_next) {
  1134. if ((p->ai_next->ai_family != AF_INET)
  1135. || SORTMATCH(p, res->sort_list[i])) {
  1136. t->ai_next = p->ai_next;
  1137. t = t->ai_next;
  1138. p->ai_next = p->ai_next->ai_next;
  1139. } else {
  1140. p = p->ai_next;
  1141. }
  1142. }
  1143. }
  1144. /* add rest of list and reset s to the new list*/
  1145. t->ai_next = s->ai_next;
  1146. s->ai_next = head.ai_next;
  1147. }
  1148. /*ARGSUSED*/
  1149. static int
  1150. _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
  1151. {
  1152. struct addrinfo *ai;
  1153. querybuf *buf, *buf2;
  1154. const char *name;
  1155. const struct addrinfo *pai;
  1156. struct addrinfo sentinel, *cur;
  1157. struct res_target q, q2;
  1158. res_state res;
  1159. name = va_arg(ap, char *);
  1160. pai = va_arg(ap, const struct addrinfo *);
  1161. memset(&q, 0, sizeof(q));
  1162. memset(&q2, 0, sizeof(q2));
  1163. memset(&sentinel, 0, sizeof(sentinel));
  1164. cur = &sentinel;
  1165. buf = malloc(sizeof(*buf));
  1166. if (buf == NULL) {
  1167. h_errno = NETDB_INTERNAL;
  1168. return NS_NOTFOUND;
  1169. }
  1170. buf2 = malloc(sizeof(*buf2));
  1171. if (buf2 == NULL) {
  1172. free(buf);
  1173. h_errno = NETDB_INTERNAL;
  1174. return NS_NOTFOUND;
  1175. }
  1176. switch (pai->ai_family) {
  1177. case AF_UNSPEC:
  1178. /* prefer IPv6 */
  1179. q.name = name;
  1180. q.qclass = C_IN;
  1181. q.qtype = T_AAAA;
  1182. q.answer = buf->buf;
  1183. q.anslen = sizeof(buf->buf);
  1184. q.next = &q2;
  1185. q2.name = name;
  1186. q2.qclass = C_IN;
  1187. q2.qtype = T_A;
  1188. q2.answer = buf2->buf;
  1189. q2.anslen = sizeof(buf2->buf);
  1190. break;
  1191. case AF_INET:
  1192. q.name = name;
  1193. q.qclass = C_IN;
  1194. q.qtype = T_A;
  1195. q.answer = buf->buf;
  1196. q.anslen = sizeof(buf->buf);
  1197. break;
  1198. case AF_INET6:
  1199. q.name = name;
  1200. q.qclass = C_IN;
  1201. q.qtype = T_AAAA;
  1202. q.answer = buf->buf;
  1203. q.anslen = sizeof(buf->buf);
  1204. break;
  1205. default:
  1206. free(buf);
  1207. free(buf2);
  1208. return NS_UNAVAIL;
  1209. }
  1210. res = __res_get_state();
  1211. if (res == NULL) {
  1212. free(buf);
  1213. free(buf2);
  1214. return NS_NOTFOUND;
  1215. }
  1216. if (res_searchN(name, &q, res) < 0) {
  1217. __res_put_state(res);
  1218. free(buf);
  1219. free(buf2);
  1220. return NS_NOTFOUND;
  1221. }
  1222. ai = getanswer(buf, q.n, q.name, q.qtype, pai);
  1223. if (ai) {
  1224. cur->ai_next = ai;
  1225. while (cur && cur->ai_next)
  1226. cur = cur->ai_next;
  1227. }
  1228. if (q.next) {
  1229. ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
  1230. if (ai)
  1231. cur->ai_next = ai;
  1232. }
  1233. free(buf);
  1234. free(buf2);
  1235. if (sentinel.ai_next == NULL) {
  1236. __res_put_state(res);
  1237. switch (h_errno) {
  1238. case HOST_NOT_FOUND:
  1239. return NS_NOTFOUND;
  1240. case TRY_AGAIN:
  1241. return NS_TRYAGAIN;
  1242. default:
  1243. return NS_UNAVAIL;
  1244. }
  1245. }
  1246. if (res->nsort)
  1247. aisort(&sentinel, res);
  1248. __res_put_state(res);
  1249. *((struct addrinfo **)rv) = sentinel.ai_next;
  1250. return NS_SUCCESS;
  1251. }
  1252. static void
  1253. _sethtent(FILE **hostf)
  1254. {
  1255. if (!*hostf)
  1256. *hostf = fopen(_PATH_HOSTS, "r" );
  1257. else
  1258. rewind(*hostf);
  1259. }
  1260. static void
  1261. _endhtent(FILE **hostf)
  1262. {
  1263. if (*hostf) {
  1264. (void) fclose(*hostf);
  1265. *hostf = NULL;
  1266. }
  1267. }
  1268. static struct addrinfo *
  1269. _gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
  1270. {
  1271. char *p;
  1272. char *cp, *tname, *cname;
  1273. struct addrinfo hints, *res0, *res;
  1274. int error;
  1275. const char *addr;
  1276. char hostbuf[8*1024];
  1277. _DIAGASSERT(name != NULL);
  1278. _DIAGASSERT(pai != NULL);
  1279. if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r" )))
  1280. return (NULL);
  1281. again:
  1282. if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf)))
  1283. return (NULL);
  1284. if (*p == '#')
  1285. goto again;
  1286. if (!(cp = strpbrk(p, "#\n")))
  1287. goto again;
  1288. *cp = '\0';
  1289. if (!(cp = strpbrk(p, " \t")))
  1290. goto again;
  1291. *cp++ = '\0';
  1292. addr = p;
  1293. /* if this is not something we're looking for, skip it. */
  1294. cname = NULL;
  1295. while (cp && *cp) {
  1296. if (*cp == ' ' || *cp == '\t') {
  1297. cp++;
  1298. continue;
  1299. }
  1300. if (!cname)
  1301. cname = cp;
  1302. tname = cp;
  1303. if ((cp = strpbrk(cp, " \t")) != NULL)
  1304. *cp++ = '\0';
  1305. if (strcasecmp(name, tname) == 0)
  1306. goto found;
  1307. }
  1308. goto again;
  1309. found:
  1310. hints = *pai;
  1311. hints.ai_flags = AI_NUMERICHOST;
  1312. error = getaddrinfo(addr, NULL, &hints, &res0);
  1313. if (error)
  1314. goto again;
  1315. for (res = res0; res; res = res->ai_next) {
  1316. /* cover it up */
  1317. res->ai_flags = pai->ai_flags;
  1318. if (pai->ai_flags & AI_CANONNAME) {
  1319. if (get_canonname(pai, res, cname) != 0) {
  1320. freeaddrinfo(res0);
  1321. goto again;
  1322. }
  1323. }
  1324. }
  1325. return res0;
  1326. }
  1327. /*ARGSUSED*/
  1328. static int
  1329. _files_getaddrinfo(void *rv, void *cb_data, va_list ap)
  1330. {
  1331. const char *name;
  1332. const struct addrinfo *pai;
  1333. struct addrinfo sentinel, *cur;
  1334. struct addrinfo *p;
  1335. #ifndef _REENTRANT
  1336. static
  1337. #endif
  1338. FILE *hostf = NULL;
  1339. name = va_arg(ap, char *);
  1340. pai = va_arg(ap, const struct addrinfo *);
  1341. memset(&sentinel, 0, sizeof(sentinel));
  1342. cur = &sentinel;
  1343. _sethtent(&hostf);
  1344. while ((p = _gethtent(&hostf, name, pai)) != NULL) {
  1345. cur->ai_next = p;
  1346. while (cur && cur->ai_next)
  1347. cur = cur->ai_next;
  1348. }
  1349. _endhtent(&hostf);
  1350. *((struct addrinfo **)rv) = sentinel.ai_next;
  1351. if (sentinel.ai_next == NULL)
  1352. return NS_NOTFOUND;
  1353. return NS_SUCCESS;
  1354. }
  1355. #ifdef YP
  1356. /*ARGSUSED*/
  1357. static struct addrinfo *
  1358. _yphostent(char *line, const struct addrinfo *pai)
  1359. {
  1360. struct addrinfo sentinel, *cur;
  1361. struct addrinfo hints, *res, *res0;
  1362. int error;
  1363. char *p;
  1364. const char *addr, *canonname;
  1365. char *nextline;
  1366. char *cp;
  1367. _DIAGASSERT(line != NULL);
  1368. _DIAGASSERT(pai != NULL);
  1369. p = line;
  1370. addr = canonname = NULL;
  1371. memset(&sentinel, 0, sizeof(sentinel));
  1372. cur = &sentinel;
  1373. nextline:
  1374. /* terminate line */
  1375. cp = strchr(p, '\n');
  1376. if (cp) {
  1377. *cp++ = '\0';
  1378. nextline = cp;
  1379. } else
  1380. nextline = NULL;
  1381. cp = strpbrk(p, " \t");
  1382. if (cp == NULL) {
  1383. if (canonname == NULL)
  1384. return (NULL);
  1385. else
  1386. goto done;
  1387. }
  1388. *cp++ = '\0';
  1389. addr = p;
  1390. while (cp && *cp) {
  1391. if (*cp == ' ' || *cp == '\t') {
  1392. cp++;
  1393. continue;
  1394. }
  1395. if (!canonname)
  1396. canonname = cp;
  1397. if ((cp = strpbrk(cp, " \t")) != NULL)
  1398. *cp++ = '\0';
  1399. }
  1400. hints = *pai;
  1401. hints.ai_flags = AI_NUMERICHOST;
  1402. error = getaddrinfo(addr, NULL, &hints, &res0);
  1403. if (error == 0) {
  1404. for (res = res0; res; res = res->ai_next) {
  1405. /* cover it up */
  1406. res->ai_flags = pai->ai_flags;
  1407. if (pai->ai_flags & AI_CANONNAME)
  1408. (void)get_canonname(pai, res, canonname);
  1409. }
  1410. } else
  1411. res0 = NULL;
  1412. if (res0) {
  1413. cur->ai_next = res0;
  1414. while (cur->ai_next)
  1415. cur = cur->ai_next;
  1416. }
  1417. if (nextline) {
  1418. p = nextline;
  1419. goto nextline;
  1420. }
  1421. done:
  1422. return sentinel.ai_next;
  1423. }
  1424. /*ARGSUSED*/
  1425. static int
  1426. _yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
  1427. {
  1428. struct addrinfo sentinel, *cur;
  1429. struct addrinfo *ai = NULL;
  1430. char *ypbuf;
  1431. int ypbuflen, r;
  1432. const char *name;
  1433. const struct addrinfo *pai;
  1434. char *ypdomain;
  1435. if (_yp_check(&ypdomain) == 0)
  1436. return NS_UNAVAIL;
  1437. name = va_arg(ap, char *);
  1438. pai = va_arg(ap, const struct addrinfo *);
  1439. memset(&sentinel, 0, sizeof(sentinel));
  1440. cur = &sentinel;
  1441. /* hosts.byname is only for IPv4 (Solaris8) */
  1442. if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
  1443. r = yp_match(ypdomain, "hosts.byname", name,
  1444. (int)strlen(name), &ypbuf, &ypbuflen);
  1445. if (r == 0) {
  1446. struct addrinfo ai4;
  1447. ai4 = *pai;
  1448. ai4.ai_family = AF_INET;
  1449. ai = _yphostent(ypbuf, &ai4);
  1450. if (ai) {
  1451. cur->ai_next = ai;
  1452. while (cur && cur->ai_next)
  1453. cur = cur->ai_next;
  1454. }
  1455. }
  1456. free(ypbuf);
  1457. }
  1458. /* ipnodes.byname can hold both IPv4/v6 */
  1459. r = yp_match(ypdomain, "ipnodes.byname", name,
  1460. (int)strlen(name), &ypbuf, &ypbuflen);
  1461. if (r == 0) {
  1462. ai = _yphostent(ypbuf, pai);
  1463. if (ai)
  1464. cur->ai_next = ai;
  1465. free(ypbuf);
  1466. }
  1467. if (sentinel.ai_next == NULL) {
  1468. h_errno = HOST_NOT_FOUND;
  1469. return NS_NOTFOUND;
  1470. }
  1471. *((struct addrinfo **)rv) = sentinel.ai_next;
  1472. return NS_SUCCESS;
  1473. }
  1474. #endif
  1475. /* resolver logic */
  1476. /*
  1477. * Formulate a normal query, send, and await answer.
  1478. * Returned answer is placed in supplied buffer "answer".
  1479. * Perform preliminary check of answer, returning success only
  1480. * if no error is indicated and the answer count is nonzero.
  1481. * Return the size of the response on success, -1 on error.
  1482. * Error number is left in h_errno.
  1483. *
  1484. * Caller must parse answer and determine whether it answers the question.
  1485. */
  1486. static int
  1487. res_queryN(const char *name, /* domain name */ struct res_target *target,
  1488. res_state res)
  1489. {
  1490. u_char buf[MAXPACKET];
  1491. HEADER *hp;
  1492. int n;
  1493. struct res_target *t;
  1494. int rcode;
  1495. int ancount;
  1496. _DIAGASSERT(name != NULL);
  1497. /* XXX: target may be NULL??? */
  1498. rcode = NOERROR;
  1499. ancount = 0;
  1500. for (t = target; t; t = t->next) {
  1501. int class, type;
  1502. u_char *answer;
  1503. int anslen;
  1504. hp = (HEADER *)(void *)t->answer;
  1505. hp->rcode = NOERROR; /* default */
  1506. /* make it easier... */
  1507. class = t->qclass;
  1508. type = t->qtype;
  1509. answer = t->answer;
  1510. anslen = t->anslen;
  1511. #ifdef DEBUG
  1512. if (res->options & RES_DEBUG)
  1513. printf(";; res_nquery(%s, %d, %d)\n", name, class, type);
  1514. #endif
  1515. n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL,
  1516. buf, sizeof(buf));
  1517. #ifdef RES_USE_EDNS0
  1518. if (n > 0 && (res->options & RES_USE_EDNS0) != 0)
  1519. n = res_nopt(res, n, buf, sizeof(buf), anslen);
  1520. #endif
  1521. if (n <= 0) {
  1522. #ifdef DEBUG
  1523. if (res->options & RES_DEBUG)
  1524. printf(";; res_nquery: mkquery failed\n");
  1525. #endif
  1526. h_errno = NO_RECOVERY;
  1527. return n;
  1528. }
  1529. n = res_nsend(res, buf, n, answer, anslen);
  1530. #if 0
  1531. if (n < 0) {
  1532. #ifdef DEBUG
  1533. if (res->options & RES_DEBUG)
  1534. printf(";; res_query: send error\n");
  1535. #endif
  1536. h_errno = TRY_AGAIN;
  1537. return n;
  1538. }
  1539. #endif
  1540. if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
  1541. rcode = hp->rcode; /* record most recent error */
  1542. #ifdef DEBUG
  1543. if (res->options & RES_DEBUG)
  1544. printf(";; rcode = %u, ancount=%u\n", hp->rcode,
  1545. ntohs(hp->ancount));
  1546. #endif
  1547. continue;
  1548. }
  1549. ancount += ntohs(hp->ancount);
  1550. t->n = n;
  1551. }
  1552. if (ancount == 0) {
  1553. switch (rcode) {
  1554. case NXDOMAIN:
  1555. h_errno = HOST_NOT_FOUND;
  1556. break;
  1557. case SERVFAIL:
  1558. h_errno = TRY_AGAIN;
  1559. break;
  1560. case NOERROR:
  1561. h_errno = NO_DATA;
  1562. break;
  1563. case FORMERR:
  1564. case NOTIMP:
  1565. case REFUSED:
  1566. default:
  1567. h_errno = NO_RECOVERY;
  1568. break;
  1569. }
  1570. return -1;
  1571. }
  1572. return ancount;
  1573. }
  1574. /*
  1575. * Formulate a normal query, send, and retrieve answer in supplied buffer.
  1576. * Return the size of the response on success, -1 on error.
  1577. * If enabled, implement search rules until answer or unrecoverable failure
  1578. * is detected. Error code, if any, is left in h_errno.
  1579. */
  1580. static int
  1581. res_searchN(const char *name, struct res_target *target, res_state res)
  1582. {
  1583. const char *cp, * const *domain;
  1584. HEADER *hp;
  1585. u_int dots;
  1586. int trailing_dot, ret, saved_herrno;
  1587. int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
  1588. _DIAGASSERT(name != NULL);
  1589. _DIAGASSERT(target != NULL);
  1590. hp = (HEADER *)(void *)target->answer; /*XXX*/
  1591. errno = 0;
  1592. h_errno = HOST_NOT_FOUND; /* default, if we never query */
  1593. dots = 0;
  1594. for (cp = name; *cp; cp++)
  1595. dots += (*cp == '.');
  1596. trailing_dot = 0;
  1597. if (cp > name && *--cp == '.')
  1598. trailing_dot++;
  1599. /*
  1600. * if there aren't any dots, it could be a user-level alias
  1601. */
  1602. if (!dots && (cp = __hostalias(name)) != NULL) {
  1603. ret = res_queryN(cp, target, res);
  1604. return ret;
  1605. }
  1606. /*
  1607. * If there are dots in the name already, let's just give it a try
  1608. * 'as is'. The threshold can be set with the "ndots" option.
  1609. */
  1610. saved_herrno = -1;
  1611. if (dots >= res->ndots) {
  1612. ret = res_querydomainN(name, NULL, target, res);
  1613. if (ret > 0)
  1614. return (ret);
  1615. saved_herrno = h_errno;
  1616. tried_as_is++;
  1617. }
  1618. /*
  1619. * We do at least one level of search if
  1620. * - there is no dot and RES_DEFNAME is set, or
  1621. * - there is at least one dot, there is no trailing dot,
  1622. * and RES_DNSRCH is set.
  1623. */
  1624. if ((!dots && (res->options & RES_DEFNAMES)) ||
  1625. (dots && !trailing_dot && (res->options & RES_DNSRCH))) {
  1626. int done = 0;
  1627. for (domain = (const char * const *)res->dnsrch;
  1628. *domain && !done;
  1629. domain++) {
  1630. ret = res_querydomainN(name, *domain, target, res);
  1631. if (ret > 0)
  1632. return ret;
  1633. /*
  1634. * If no server present, give up.
  1635. * If name isn't found in this domain,
  1636. * keep trying higher domains in the search list
  1637. * (if that's enabled).
  1638. * On a NO_DATA error, keep trying, otherwise
  1639. * a wildcard entry of another type could keep us
  1640. * from finding this entry higher in the domain.
  1641. * If we get some other error (negative answer or
  1642. * server failure), then stop searching up,
  1643. * but try the input name below in case it's
  1644. * fully-qualified.
  1645. */
  1646. if (errno == ECONNREFUSED) {
  1647. h_errno = TRY_AGAIN;
  1648. return -1;
  1649. }
  1650. switch (h_errno) {
  1651. case NO_DATA:
  1652. got_nodata++;
  1653. /* FALLTHROUGH */
  1654. case HOST_NOT_FOUND:
  1655. /* keep trying */
  1656. break;
  1657. case TRY_AGAIN:
  1658. if (hp->rcode == SERVFAIL) {
  1659. /* try next search element, if any */
  1660. got_servfail++;
  1661. break;
  1662. }
  1663. /* FALLTHROUGH */
  1664. default:
  1665. /* anything else implies that we're done */
  1666. done++;
  1667. }
  1668. /*
  1669. * if we got here for some reason other than DNSRCH,
  1670. * we only wanted one iteration of the loop, so stop.
  1671. */
  1672. if (!(res->options & RES_DNSRCH))
  1673. done++;
  1674. }
  1675. }
  1676. /*
  1677. * if we have not already tried the name "as is", do that now.
  1678. * note that we do this regardless of how many dots were in the
  1679. * name or whether it ends with a dot.
  1680. */
  1681. if (!tried_as_is) {
  1682. ret = res_querydomainN(name, NULL, target, res);
  1683. if (ret > 0)
  1684. return ret;
  1685. }
  1686. /*
  1687. * if we got here, we didn't satisfy the search.
  1688. * if we did an initial full query, return that query's h_errno
  1689. * (note that we wouldn't be here if that query had succeeded).
  1690. * else if we ever got a nodata, send that back as the reason.
  1691. * else send back meaningless h_errno, that being the one from
  1692. * the last DNSRCH we did.
  1693. */
  1694. if (saved_herrno != -1)
  1695. h_errno = saved_herrno;
  1696. else if (got_nodata)
  1697. h_errno = NO_DATA;
  1698. else if (got_servfail)
  1699. h_errno = TRY_AGAIN;
  1700. return -1;
  1701. }
  1702. /*
  1703. * Perform a call on res_query on the concatenation of name and domain,
  1704. * removing a trailing dot from name if domain is NULL.
  1705. */
  1706. static int
  1707. res_querydomainN(const char *name, const char *domain,
  1708. struct res_target *target, res_state res)
  1709. {
  1710. char nbuf[MAXDNAME];
  1711. const char *longname = nbuf;
  1712. size_t n, d;
  1713. _DIAGASSERT(name != NULL);
  1714. /* XXX: target may be NULL??? */
  1715. #ifdef DEBUG
  1716. if (res->options & RES_DEBUG)
  1717. printf(";; res_querydomain(%s, %s)\n",
  1718. name, domain?domain:"<Nil>");
  1719. #endif
  1720. if (domain == NULL) {
  1721. /*
  1722. * Check for trailing '.';
  1723. * copy without '.' if present.
  1724. */
  1725. n = strlen(name);
  1726. if (n + 1 > sizeof(nbuf)) {
  1727. h_errno = NO_RECOVERY;
  1728. return -1;
  1729. }
  1730. if (n > 0 && name[--n] == '.') {
  1731. strncpy(nbuf, name, n);
  1732. nbuf[n] = '\0';
  1733. } else
  1734. longname = name;
  1735. } else {
  1736. n = strlen(name);
  1737. d = strlen(domain);
  1738. if (n + 1 + d + 1 > sizeof(nbuf)) {
  1739. h_errno = NO_RECOVERY;
  1740. return -1;
  1741. }
  1742. snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
  1743. }
  1744. return res_queryN(longname, target, res);
  1745. }