summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/getaddrinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/net/getaddrinfo.c')
-rw-r--r--src/lib/libc/net/getaddrinfo.c76
1 files changed, 47 insertions, 29 deletions
diff --git a/src/lib/libc/net/getaddrinfo.c b/src/lib/libc/net/getaddrinfo.c
index 915286a404..7406f10714 100644
--- a/src/lib/libc/net/getaddrinfo.c
+++ b/src/lib/libc/net/getaddrinfo.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: getaddrinfo.c,v 1.43 2002/08/27 08:53:13 itojun Exp $ */ 1/* $OpenBSD: getaddrinfo.c,v 1.44 2003/01/28 04:58:00 marc Exp $ */
2/* $KAME: getaddrinfo.c,v 1.31 2000/08/31 17:36:43 itojun Exp $ */ 2/* $KAME: getaddrinfo.c,v 1.31 2000/08/31 17:36:43 itojun Exp $ */
3 3
4/* 4/*
@@ -499,8 +499,6 @@ getaddrinfo(hostname, servname, hints, res)
499 * FQDN hostname, DNS lookup 499 * FQDN hostname, DNS lookup
500 */ 500 */
501 501
502_THREAD_PRIVATE_MUTEX(getaddrinfo_explore_fqdn);
503
504static int 502static int
505explore_fqdn(pai, hostname, servname, res) 503explore_fqdn(pai, hostname, servname, res)
506 const struct addrinfo *pai; 504 const struct addrinfo *pai;
@@ -508,13 +506,13 @@ explore_fqdn(pai, hostname, servname, res)
508 const char *servname; 506 const char *servname;
509 struct addrinfo **res; 507 struct addrinfo **res;
510{ 508{
509 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
511 struct addrinfo *result; 510 struct addrinfo *result;
512 struct addrinfo *cur; 511 struct addrinfo *cur;
513 int error = 0; 512 int error = 0;
514 char lookups[MAXDNSLUS]; 513 char lookups[MAXDNSLUS];
515 int i; 514 int i;
516 515 _THREAD_PRIVATE_MUTEX(_explore_mutex);
517 _THREAD_PRIVATE_MUTEX_LOCK(getaddrinfo_explore_fqdn);
518 516
519 result = NULL; 517 result = NULL;
520 518
@@ -525,7 +523,6 @@ explore_fqdn(pai, hostname, servname, res)
525 * XXX does not handle PF_UNSPEC case, should filter final result 523 * XXX does not handle PF_UNSPEC case, should filter final result
526 */ 524 */
527 if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(pai)) { 525 if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(pai)) {
528 _THREAD_PRIVATE_MUTEX_UNLOCK(getaddrinfo_explore_fqdn);
529 return 0; 526 return 0;
530 } 527 }
531#endif 528#endif
@@ -534,18 +531,22 @@ explore_fqdn(pai, hostname, servname, res)
534 * if the servname does not match socktype/protocol, ignore it. 531 * if the servname does not match socktype/protocol, ignore it.
535 */ 532 */
536 if (get_portmatch(pai, servname) != 0) { 533 if (get_portmatch(pai, servname) != 0) {
537 _THREAD_PRIVATE_MUTEX_UNLOCK(getaddrinfo_explore_fqdn);
538 return 0; 534 return 0;
539 } 535 }
540 536
541 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 537 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
542 strlcpy(lookups, "f", sizeof lookups); 538 strlcpy(lookups, "f", sizeof lookups);
543 else { 539 else {
544 bcopy(_res.lookups, lookups, sizeof lookups); 540 bcopy(_resp->lookups, lookups, sizeof lookups);
545 if (lookups[0] == '\0') 541 if (lookups[0] == '\0')
546 strlcpy(lookups, "bf", sizeof lookups); 542 strlcpy(lookups, "bf", sizeof lookups);
547 } 543 }
548 544
545 /*
546 * The yp/dns/files getaddrinfo functions are not thread safe.
547 * Protect them with a mutex.
548 */
549 _THREAD_PRIVATE_MUTEX_LOCK(_explore_mutex);
549 for (i = 0; i < MAXDNSLUS && result == NULL && lookups[i]; i++) { 550 for (i = 0; i < MAXDNSLUS && result == NULL && lookups[i]; i++) {
550 switch (lookups[i]) { 551 switch (lookups[i]) {
551#ifdef YP 552#ifdef YP
@@ -561,13 +562,13 @@ explore_fqdn(pai, hostname, servname, res)
561 break; 562 break;
562 } 563 }
563 } 564 }
565 _THREAD_PRIVATE_MUTEX_UNLOCK(_explore_mutex);
564 if (result) { 566 if (result) {
565 for (cur = result; cur; cur = cur->ai_next) { 567 for (cur = result; cur; cur = cur->ai_next) {
566 GET_PORT(cur, servname); 568 GET_PORT(cur, servname);
567 /* canonname should be filled already */ 569 /* canonname should be filled already */
568 } 570 }
569 *res = result; 571 *res = result;
570 _THREAD_PRIVATE_MUTEX_UNLOCK(getaddrinfo_explore_fqdn);
571 return 0; 572 return 0;
572 } else { 573 } else {
573 /* translate error code */ 574 /* translate error code */
@@ -599,7 +600,6 @@ explore_fqdn(pai, hostname, servname, res)
599free: 600free:
600 if (result) 601 if (result)
601 freeaddrinfo(result); 602 freeaddrinfo(result);
602 _THREAD_PRIVATE_MUTEX_UNLOCK(getaddrinfo_explore_fqdn);
603 return error; 603 return error;
604} 604}
605 605
@@ -867,6 +867,7 @@ get_port(ai, servname, matchonly)
867 struct servent *sp; 867 struct servent *sp;
868 int port; 868 int port;
869 int allownumeric; 869 int allownumeric;
870 _THREAD_PRIVATE_MUTEX(serv_mutex);
870 871
871 if (servname == NULL) 872 if (servname == NULL)
872 return 0; 873 return 0;
@@ -914,7 +915,10 @@ get_port(ai, servname, matchonly)
914 break; 915 break;
915 } 916 }
916 917
917 if ((sp = getservbyname(servname, proto)) == NULL) 918 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
919 sp = getservbyname(servname, proto);
920 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
921 if (sp == NULL)
918 return EAI_SERVICE; 922 return EAI_SERVICE;
919 port = sp->s_port; 923 port = sp->s_port;
920 } 924 }
@@ -1563,18 +1567,26 @@ res_queryN(name, target)
1563 const char *name; /* domain name */ 1567 const char *name; /* domain name */
1564 struct res_target *target; 1568 struct res_target *target;
1565{ 1569{
1566 u_char buf[MAXPACKET]; 1570 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1571 u_char *buf;
1567 HEADER *hp; 1572 HEADER *hp;
1568 int n; 1573 int n;
1569 struct res_target *t; 1574 struct res_target *t;
1570 int rcode; 1575 int rcode;
1571 int ancount; 1576 int ancount;
1572 1577
1578 buf = malloc(MAXPACKET);
1579 if (buf == NULL) {
1580 h_errno = NETDB_INTERNAL;
1581 return (-1);
1582 }
1583
1573 rcode = NOERROR; 1584 rcode = NOERROR;
1574 ancount = 0; 1585 ancount = 0;
1575 1586
1576 if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 1587 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
1577 h_errno = NETDB_INTERNAL; 1588 h_errno = NETDB_INTERNAL;
1589 free(buf);
1578 return (-1); 1590 return (-1);
1579 } 1591 }
1580 1592
@@ -1592,30 +1604,32 @@ res_queryN(name, target)
1592 answer = t->answer; 1604 answer = t->answer;
1593 anslen = t->anslen; 1605 anslen = t->anslen;
1594#ifdef DEBUG 1606#ifdef DEBUG
1595 if (_res.options & RES_DEBUG) 1607 if (_resp->options & RES_DEBUG)
1596 printf(";; res_query(%s, %d, %d)\n", name, class, type); 1608 printf(";; res_query(%s, %d, %d)\n", name, class, type);
1597#endif 1609#endif
1598 1610
1599 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL, 1611 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
1600 buf, sizeof(buf)); 1612 buf, MAXPACKET);
1601 if (n > 0 && (_res.options & RES_USE_EDNS0) != 0) 1613 if (n > 0 && (_resp->options & RES_USE_EDNS0) != 0)
1602 n = res_opt(n, buf, sizeof(buf), anslen); 1614 n = res_opt(n, buf, MAXPACKET, anslen);
1603 if (n <= 0) { 1615 if (n <= 0) {
1604#ifdef DEBUG 1616#ifdef DEBUG
1605 if (_res.options & RES_DEBUG) 1617 if (_resp->options & RES_DEBUG)
1606 printf(";; res_query: mkquery failed\n"); 1618 printf(";; res_query: mkquery failed\n");
1607#endif 1619#endif
1608 h_errno = NO_RECOVERY; 1620 h_errno = NO_RECOVERY;
1621 free(buf);
1609 return (n); 1622 return (n);
1610 } 1623 }
1611 n = res_send(buf, n, answer, anslen); 1624 n = res_send(buf, n, answer, anslen);
1612#if 0 1625#if 0
1613 if (n < 0) { 1626 if (n < 0) {
1614#ifdef DEBUG 1627#ifdef DEBUG
1615 if (_res.options & RES_DEBUG) 1628 if (_resp->options & RES_DEBUG)
1616 printf(";; res_query: send error\n"); 1629 printf(";; res_query: send error\n");
1617#endif 1630#endif
1618 h_errno = TRY_AGAIN; 1631 h_errno = TRY_AGAIN;
1632 free(buf);
1619 return (n); 1633 return (n);
1620 } 1634 }
1621#endif 1635#endif
@@ -1623,7 +1637,7 @@ res_queryN(name, target)
1623 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 1637 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
1624 rcode = hp->rcode; /* record most recent error */ 1638 rcode = hp->rcode; /* record most recent error */
1625#ifdef DEBUG 1639#ifdef DEBUG
1626 if (_res.options & RES_DEBUG) 1640 if (_resp->options & RES_DEBUG)
1627 printf(";; rcode = %u, ancount=%u\n", hp->rcode, 1641 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
1628 ntohs(hp->ancount)); 1642 ntohs(hp->ancount));
1629#endif 1643#endif
@@ -1653,8 +1667,10 @@ res_queryN(name, target)
1653 h_errno = NO_RECOVERY; 1667 h_errno = NO_RECOVERY;
1654 break; 1668 break;
1655 } 1669 }
1670 free(buf);
1656 return (-1); 1671 return (-1);
1657 } 1672 }
1673 free(buf);
1658 return (ancount); 1674 return (ancount);
1659} 1675}
1660 1676
@@ -1669,13 +1685,14 @@ res_searchN(name, target)
1669 const char *name; /* domain name */ 1685 const char *name; /* domain name */
1670 struct res_target *target; 1686 struct res_target *target;
1671{ 1687{
1688 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1672 const char *cp, * const *domain; 1689 const char *cp, * const *domain;
1673 HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/ 1690 HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/
1674 u_int dots; 1691 u_int dots;
1675 int trailing_dot, ret, saved_herrno; 1692 int trailing_dot, ret, saved_herrno;
1676 int got_nodata = 0, got_servfail = 0, tried_as_is = 0; 1693 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
1677 1694
1678 if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 1695 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
1679 h_errno = NETDB_INTERNAL; 1696 h_errno = NETDB_INTERNAL;
1680 return (-1); 1697 return (-1);
1681 } 1698 }
@@ -1700,7 +1717,7 @@ res_searchN(name, target)
1700 * 'as is'. The threshold can be set with the "ndots" option. 1717 * 'as is'. The threshold can be set with the "ndots" option.
1701 */ 1718 */
1702 saved_herrno = -1; 1719 saved_herrno = -1;
1703 if (dots >= _res.ndots) { 1720 if (dots >= _resp->ndots) {
1704 ret = res_querydomainN(name, NULL, target); 1721 ret = res_querydomainN(name, NULL, target);
1705 if (ret > 0) 1722 if (ret > 0)
1706 return (ret); 1723 return (ret);
@@ -1714,11 +1731,11 @@ res_searchN(name, target)
1714 * - there is at least one dot, there is no trailing dot, 1731 * - there is at least one dot, there is no trailing dot,
1715 * and RES_DNSRCH is set. 1732 * and RES_DNSRCH is set.
1716 */ 1733 */
1717 if ((!dots && (_res.options & RES_DEFNAMES)) || 1734 if ((!dots && (_resp->options & RES_DEFNAMES)) ||
1718 (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { 1735 (dots && !trailing_dot && (_resp->options & RES_DNSRCH))) {
1719 int done = 0; 1736 int done = 0;
1720 1737
1721 for (domain = (const char * const *)_res.dnsrch; 1738 for (domain = (const char * const *)_resp->dnsrch;
1722 *domain && !done; 1739 *domain && !done;
1723 domain++) { 1740 domain++) {
1724 1741
@@ -1766,7 +1783,7 @@ res_searchN(name, target)
1766 * if we got here for some reason other than DNSRCH, 1783 * if we got here for some reason other than DNSRCH,
1767 * we only wanted one iteration of the loop, so stop. 1784 * we only wanted one iteration of the loop, so stop.
1768 */ 1785 */
1769 if (!(_res.options & RES_DNSRCH)) 1786 if (!(_resp->options & RES_DNSRCH))
1770 done++; 1787 done++;
1771 } 1788 }
1772 } 1789 }
@@ -1808,16 +1825,17 @@ res_querydomainN(name, domain, target)
1808 const char *name, *domain; 1825 const char *name, *domain;
1809 struct res_target *target; 1826 struct res_target *target;
1810{ 1827{
1828 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1811 char nbuf[MAXDNAME]; 1829 char nbuf[MAXDNAME];
1812 const char *longname = nbuf; 1830 const char *longname = nbuf;
1813 size_t n, d; 1831 size_t n, d;
1814 1832
1815 if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 1833 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
1816 h_errno = NETDB_INTERNAL; 1834 h_errno = NETDB_INTERNAL;
1817 return (-1); 1835 return (-1);
1818 } 1836 }
1819#ifdef DEBUG 1837#ifdef DEBUG
1820 if (_res.options & RES_DEBUG) 1838 if (_resp->options & RES_DEBUG)
1821 printf(";; res_querydomain(%s, %s)\n", 1839 printf(";; res_querydomain(%s, %s)\n",
1822 name, domain?domain:"<Nil>"); 1840 name, domain?domain:"<Nil>");
1823#endif 1841#endif