diff options
Diffstat (limited to 'src/lib/libc/net/getaddrinfo.c')
| -rw-r--r-- | src/lib/libc/net/getaddrinfo.c | 76 | 
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 | |||
| 504 | static int | 502 | static int | 
| 505 | explore_fqdn(pai, hostname, servname, res) | 503 | explore_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) | |||
| 599 | free: | 600 | free: | 
| 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 | 
