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 |