diff options
Diffstat (limited to 'libc/inet')
112 files changed, 5330 insertions, 5151 deletions
diff --git a/libc/inet/Makefile.in b/libc/inet/Makefile.in index 493041ff6..3bfe4b29e 100644 --- a/libc/inet/Makefile.in +++ b/libc/inet/Makefile.in @@ -1,63 +1,66 @@ # Makefile for uClibc # -# Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> +# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org> # # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. # +subdirs += libc/inet + include $(top_srcdir)libc/inet/rpc/Makefile.in INET_DIR := $(top_srcdir)libc/inet INET_OUT := $(top_builddir)libc/inet +V4_OR_V6 := $(findstring y,$(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6)) -CSRC := -ifneq ($(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6),) -CSRC += getservice.c getproto.c hostid.c getnetent.c getnetbynm.c getnetbyad.c \ +CFLAGS-y-libc/inet := -DRESOLVER="\"resolv.c\"" +CSRC-y := +# des uses ntohl +CSRC-$(findstring y,$(UCLIBC_HAS_CRYPT_IMPL)$(V4_OR_V6)) += ntohl.c +CSRC-$(V4_OR_V6) += \ + getservice.c getproto.c getnet.c hostid.c \ inet_net.c herror.c if_index.c gai_strerror.c getaddrinfo.c \ - ether_addr.c ntohl.c ifaddrs.c ntop.c -endif -ifeq ($(UCLIBC_HAS_IPV6),y) -CSRC += in6_addr.c -endif - + ifaddrs.c ntop.c +CSRC-$(UCLIBC_HAS_IPV6) += in6_addr.c # multi source addr.c -addr_CSRC := inet_aton.c inet_addr.c inet_ntoa.c inet_makeaddr.c \ +CSRC-$(V4_OR_V6) += \ + inet_aton.c inet_addr.c inet_ntoa.c inet_makeaddr.c \ inet_lnaof.c inet_netof.c -ifneq ($(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6),) -CSRC += $(addr_CSRC) -endif - # multi source resolv.c -resolv_CSRC += encodeh.c decodeh.c encoded.c decoded.c lengthd.c encodeq.c \ - decodeq.c lengthq.c encodea.c decodea.c \ - dnslookup.c resolveaddress.c opennameservers.c \ - closenameservers.c resolvename.c gethostbyname.c res_init.c \ - res_query.c gethostbyaddr.c read_etc_hosts_r.c get_hosts_byname_r.c \ - get_hosts_byaddr_r.c gethostbyname2.c getnameinfo.c gethostent.c \ - gethostbyname_r.c gethostbyname2_r.c gethostbyaddr_r.c \ - res_comp.c ns_name.c ethers.c -ifneq ($(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6),) -CSRC += $(resolv_CSRC) - -# unused ATM -CSRC += encodep.c decodep.c formquery.c -endif - +CSRC-$(V4_OR_V6) += \ + encodeh.c decodeh.c encoded.c decoded.c \ + encodeq.c encodea.c \ + read_etc_hosts_r.c \ + dnslookup.c opennameservers.c closenameservers.c \ + getnameinfo.c \ + gethostent.c gethostent_r.c +CSRC-$(V4_OR_V6) += \ + get_hosts_byaddr_r.c get_hosts_byname_r.c \ + gethostbyaddr_r.c gethostbyname_r.c gethostbyname2_r.c \ + gethostbyaddr.c gethostbyname.c gethostbyname2.c +CSRC-$(UCLIBC_HAS_RESOLVER_SUPPORT) += \ + ns_netint.c ns_parse.c res_data.c \ + res_init.c res_query.c res_comp.c ns_name.c \ + _res_state.c +## # unused ATM +## CSRC-y += encodep.c decodep.c formquery.c # multi source socketcalls.c -socketcalls_CSRC += accept.c bind.c connect.c getpeername.c getsockname.c \ +socketcalls_CSRC-y += \ + accept.c bind.c connect.c getpeername.c getsockname.c \ getsockopt.c listen.c recv.c recvfrom.c recvmsg.c send.c sendmsg.c \ sendto.c setsockopt.c shutdown.c socket.c socketpair.c -ifeq ($(UCLIBC_HAS_SOCKET),y) -CSRC += $(socketcalls_CSRC) opensock.c -endif +socketcalls_CSRC-$(UCLIBC_LINUX_SPECIFIC) += accept4.c +CSRC-$(UCLIBC_HAS_SOCKET) += $(socketcalls_CSRC-y) opensock.c + +CSRC-$(findstring y,$(UCLIBC_HAS_SOCKET)$(V4_OR_V6)) += ethers.c ether_addr.c -INET_SRC := $(patsubst %.c,$(INET_DIR)/%.c,$(CSRC)) -INET_OBJ := $(patsubst %.c,$(INET_OUT)/%.o,$(CSRC)) +INET_SRC := $(patsubst %.c,$(INET_DIR)/%.c,$(CSRC-y)) +INET_OBJ := $(patsubst %.c,$(INET_OUT)/%.o,$(CSRC-y)) libc-y += $(INET_OBJ) -objclean-y += inet_objclean +objclean-y += CLEAN_libc/inet -inet_objclean: - $(RM) $(INET_OUT)/*.{o,os} +CLEAN_libc/inet: + $(do_rm) $(addprefix $(INET_OUT)/*., o os) diff --git a/libc/inet/_res_state.c b/libc/inet/_res_state.c new file mode 100644 index 000000000..dc0d89f40 --- /dev/null +++ b/libc/inet/_res_state.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2006 Steven J. Hill <sjhill@realitydiluted.com> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_res_state +#include RESOLVER diff --git a/libc/inet/resolveaddress.c b/libc/inet/accept4.c index d57366c98..e2fdd6c2f 100644 --- a/libc/inet/resolveaddress.c +++ b/libc/inet/accept4.c @@ -4,5 +4,5 @@ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ -#define L_resolveaddress -#include "resolv.c" +#define L_accept4 +#include "socketcalls.c" diff --git a/libc/inet/addr.c b/libc/inet/addr.c index 2a0bb84a8..cd7151a45 100644 --- a/libc/inet/addr.c +++ b/libc/inet/addr.c @@ -17,8 +17,6 @@ * Changed to use _int10tostr. */ -#define __FORCE_GLIBC -#include <features.h> #include <stdio.h> #include <string.h> #include <ctype.h> @@ -43,12 +41,6 @@ * leading 0 -> octal * all else -> decimal */ -#ifdef __UCLIBC_HAS_XLOCALE__ -libc_hidden_proto(__ctype_b_loc) -#elif defined __UCLIBC_HAS_CTYPE_TABLES__ -libc_hidden_proto(__ctype_b) -#endif -libc_hidden_proto(inet_aton) int inet_aton(const char *cp, struct in_addr *addrptr) { in_addr_t addr; @@ -103,9 +95,7 @@ libc_hidden_def(inet_aton) #endif #ifdef L_inet_addr -libc_hidden_proto(inet_aton) -libc_hidden_proto(inet_addr) in_addr_t inet_addr(const char *cp) { struct in_addr a; @@ -122,8 +112,7 @@ libc_hidden_def(inet_addr) #define INET_NTOA_MAX_LEN 16 /* max 12 digits + 3 '.'s + 1 nul */ -libc_hidden_proto(inet_ntoa_r) -char *inet_ntoa_r(struct in_addr in, char buf[INET_NTOA_MAX_LEN]) +static char *__inet_ntoa_r(struct in_addr in, char buf[INET_NTOA_MAX_LEN]) { in_addr_t addr = ntohl(in.s_addr); int i; @@ -142,13 +131,12 @@ char *inet_ntoa_r(struct in_addr in, char buf[INET_NTOA_MAX_LEN]) return p+1; } -libc_hidden_def(inet_ntoa_r) +strong_alias(__inet_ntoa_r,inet_ntoa_r) -libc_hidden_proto(inet_ntoa) char *inet_ntoa(struct in_addr in) { static char buf[INET_NTOA_MAX_LEN]; - return inet_ntoa_r(in, buf); + return __inet_ntoa_r(in, buf); } libc_hidden_def(inet_ntoa) #endif @@ -156,27 +144,25 @@ libc_hidden_def(inet_ntoa) #ifdef L_inet_makeaddr /* for some reason it does not remove the jump relocation */ -/* Experimentally off - libc_hidden_proto(memmove) */ /* * Formulate an Internet address from network + host. Used in * building addresses stored in the ifnet structure. */ -libc_hidden_proto(inet_makeaddr) struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host) { - in_addr_t addr; + struct in_addr in; if (net < 128) - addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); + in.s_addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); else if (net < 65536) - addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST); + in.s_addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST); else if (net < 16777216UL) - addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST); + in.s_addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST); else - addr = net | host; - addr = htonl(addr); - return *(struct in_addr *)&addr; + in.s_addr = net | host; + in.s_addr = htonl(in.s_addr); + return in; } libc_hidden_def(inet_makeaddr) #endif @@ -206,7 +192,6 @@ in_addr_t inet_lnaof(struct in_addr in) * Return the network number from an internet * address; handles class a/b/c network #'s. */ -libc_hidden_proto(inet_netof) in_addr_t inet_netof(struct in_addr in) { diff --git a/libc/inet/closenameservers.c b/libc/inet/closenameservers.c index ca4dae3fb..65889a79a 100644 --- a/libc/inet/closenameservers.c +++ b/libc/inet/closenameservers.c @@ -5,4 +5,4 @@ */ #define L_closenameservers -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/decodea.c b/libc/inet/decodea.c index 409a97843..112d5d9e0 100644 --- a/libc/inet/decodea.c +++ b/libc/inet/decodea.c @@ -5,4 +5,4 @@ */ #define L_decodea -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/decoded.c b/libc/inet/decoded.c index 73849ef5f..378cbfad7 100644 --- a/libc/inet/decoded.c +++ b/libc/inet/decoded.c @@ -5,4 +5,4 @@ */ #define L_decoded -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/decodeh.c b/libc/inet/decodeh.c index 86681fa88..7744287f6 100644 --- a/libc/inet/decodeh.c +++ b/libc/inet/decodeh.c @@ -5,4 +5,4 @@ */ #define L_decodeh -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/decodep.c b/libc/inet/decodep.c index 40b0bda0d..0e946e01f 100644 --- a/libc/inet/decodep.c +++ b/libc/inet/decodep.c @@ -5,4 +5,4 @@ */ #define L_decodep -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/decodeq.c b/libc/inet/decodeq.c index a6109677e..9e36b95d4 100644 --- a/libc/inet/decodeq.c +++ b/libc/inet/decodeq.c @@ -5,4 +5,4 @@ */ #define L_decodeq -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/dnslookup.c b/libc/inet/dnslookup.c index 4ffc34f0a..b9f59a2ff 100644 --- a/libc/inet/dnslookup.c +++ b/libc/inet/dnslookup.c @@ -5,4 +5,4 @@ */ #define L_dnslookup -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/encodea.c b/libc/inet/encodea.c index 628f9bad5..b42ee4a79 100644 --- a/libc/inet/encodea.c +++ b/libc/inet/encodea.c @@ -5,4 +5,4 @@ */ #define L_encodea -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/encoded.c b/libc/inet/encoded.c index d60618771..27f92becd 100644 --- a/libc/inet/encoded.c +++ b/libc/inet/encoded.c @@ -5,4 +5,4 @@ */ #define L_encoded -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/encodeh.c b/libc/inet/encodeh.c index 1d5488017..6a69a948b 100644 --- a/libc/inet/encodeh.c +++ b/libc/inet/encodeh.c @@ -5,4 +5,4 @@ */ #define L_encodeh -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/encodep.c b/libc/inet/encodep.c index d2f248b40..d298c2131 100644 --- a/libc/inet/encodep.c +++ b/libc/inet/encodep.c @@ -5,4 +5,4 @@ */ #define L_encodep -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/encodeq.c b/libc/inet/encodeq.c index be1a3123b..5555aa548 100644 --- a/libc/inet/encodeq.c +++ b/libc/inet/encodeq.c @@ -5,4 +5,4 @@ */ #define L_encodeq -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/ether_addr.c b/libc/inet/ether_addr.c index bcea9ba46..6d456e716 100644 --- a/libc/inet/ether_addr.c +++ b/libc/inet/ether_addr.c @@ -13,9 +13,8 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. + License along with the GNU C Library; see the file COPYING.LIB. If + not, see <http://www.gnu.org/licenses/>. */ /* @@ -23,58 +22,53 @@ * - initial uClibc port */ -#define __FORCE_GLIBC -#include <features.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <netinet/ether.h> #include <netinet/if_ether.h> -libc_hidden_proto(ether_aton_r) -libc_hidden_proto(ether_ntoa_r) -libc_hidden_proto(sprintf) -#ifdef __UCLIBC_HAS_XLOCALE__ -libc_hidden_proto(__ctype_b_loc) -libc_hidden_proto(__ctype_tolower_loc) -#elif defined __UCLIBC_HAS_CTYPE_TABLES__ -libc_hidden_proto(__ctype_b) -libc_hidden_proto(__ctype_tolower) -#endif - struct ether_addr *ether_aton_r(const char *asc, struct ether_addr *addr) { - size_t cnt; + /* asc is "X:XX:XX:x:xx:xX" */ + int cnt; for (cnt = 0; cnt < 6; ++cnt) { - unsigned int number; - char ch; + unsigned char number; + char ch = *asc++; - ch = _tolower(*asc++); + if (ch < 0x20) + return NULL; + /* | 0x20 is cheap tolower(), valid for letters/numbers only */ + ch |= 0x20; if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f')) return NULL; - number = isdigit(ch) ? (ch - '0') : (ch - 'a' + 10); - - ch = _tolower(*asc); - if ((cnt < 5 && ch != ':') - || (cnt == 5 && ch != '\0' && !isspace(ch))) { - ++asc; + number = !(ch > '9') ? (ch - '0') : (ch - 'a' + 10); + + ch = *asc++; + if ((cnt != 5 && ch != ':') /* not last group */ + /* What standard says ASCII ether address representation + * may also finish with whitespace, not only NUL? + * We can get rid of isspace() otherwise */ + || (cnt == 5 && ch != '\0' /*&& !isspace(ch)*/) + ) { + ch |= 0x20; /* cheap tolower() */ if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f')) return NULL; - number <<= 4; - number += isdigit(ch) ? (ch - '0') : (ch - 'a' + 10); + number = (number << 4) + (!(ch > '9') ? (ch - '0') : (ch - 'a' + 10)); - ch = *asc; - if (cnt < 5 && ch != ':') - return NULL; + if (cnt != 5) { + ch = *asc++; + if (ch != ':') + return NULL; + } } /* Store result. */ - addr->ether_addr_octet[cnt] = (unsigned char) number; - - /* Skip ':'. */ - ++asc; + addr->ether_addr_octet[cnt] = number; } + /* Looks like we allow garbage after last group? + * "1:2:3:4:5:66anything_at_all"? */ return addr; } diff --git a/libc/inet/formquery.c b/libc/inet/formquery.c index 2c53e33de..4bc0ebe3f 100644 --- a/libc/inet/formquery.c +++ b/libc/inet/formquery.c @@ -5,4 +5,4 @@ */ #define L_formquery -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/gai_strerror.c b/libc/inet/gai_strerror.c index 61688bad9..1da55524a 100644 --- a/libc/inet/gai_strerror.c +++ b/libc/inet/gai_strerror.c @@ -13,17 +13,13 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ -#define __FORCE_GLIBC -#include <features.h> #include <stdio.h> #include <netdb.h> +#include <libintl.h> -#define N_(x) x -#define _(x) x static const struct { int code; diff --git a/libc/inet/get_hosts_byaddr_r.c b/libc/inet/get_hosts_byaddr_r.c index c377aec13..eeac8907f 100644 --- a/libc/inet/get_hosts_byaddr_r.c +++ b/libc/inet/get_hosts_byaddr_r.c @@ -5,4 +5,4 @@ */ #define L_get_hosts_byaddr_r -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/get_hosts_byname_r.c b/libc/inet/get_hosts_byname_r.c index 7ad1e3fa5..caad0bcc7 100644 --- a/libc/inet/get_hosts_byname_r.c +++ b/libc/inet/get_hosts_byname_r.c @@ -5,4 +5,4 @@ */ #define L_get_hosts_byname_r -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/getaddrinfo.c b/libc/inet/getaddrinfo.c index df802f1d4..7ae32be39 100644 --- a/libc/inet/getaddrinfo.c +++ b/libc/inet/getaddrinfo.c @@ -51,16 +51,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If these license terms cause you a real problem, contact the author. */ -#define __FORCE_GLIBC -#include <features.h> #include <assert.h> #include <errno.h> #include <netdb.h> +#ifdef __UCLIBC_HAS_TLS__ +#include <tls.h> +#endif #include <resolv.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <stdbool.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> @@ -69,28 +71,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <sys/utsname.h> #include <net/if.h> #include <ifaddrs.h> - -/* Experimentally off - libc_hidden_proto(memcpy) */ -/* Experimentally off - libc_hidden_proto(memset) */ -/* libc_hidden_proto(strcmp) */ -/* libc_hidden_proto(stpcpy) */ -/* Experimentally off - libc_hidden_proto(strchr) */ -/* Experimentally off - libc_hidden_proto(strcpy) */ -/* Experimentally off - libc_hidden_proto(strlen) */ -libc_hidden_proto(socket) -libc_hidden_proto(close) -libc_hidden_proto(getservbyname_r) -libc_hidden_proto(gethostbyname2_r) -libc_hidden_proto(gethostbyaddr_r) -libc_hidden_proto(inet_pton) -libc_hidden_proto(inet_ntop) -libc_hidden_proto(strtoul) -libc_hidden_proto(if_nametoindex) -libc_hidden_proto(__h_errno_location) -/* libc_hidden_proto(uname) */ -#ifdef __UCLIBC_HAS_IPV6__ -libc_hidden_proto(in6addr_loopback) -#endif +#include "internal/parse_config.h" #define GAIH_OKIFUNSPEC 0x0100 #define GAIH_EAI ~(GAIH_OKIFUNSPEC) @@ -99,888 +80,899 @@ libc_hidden_proto(in6addr_loopback) #define UNIX_PATH_MAX 108 #endif -struct gaih_service -{ - const char *name; - int num; +/* Useful for having small structure members/global variables */ +typedef int8_t socktype_t; +typedef int8_t family_t; +typedef int8_t protocol_t; +struct BUG_too_small { + char BUG_socktype_t_too_small[(0 + | SOCK_STREAM + | SOCK_DGRAM + | SOCK_RAW + ) <= 127 ? 1 : -1]; + char BUG_family_t_too_small[(0 + | AF_UNSPEC + | AF_INET + | AF_INET6 + ) <= 127 ? 1 : -1]; + char BUG_protocol_t_too_small[(0 + | IPPROTO_TCP + | IPPROTO_UDP + ) <= 127 ? 1 : -1]; }; -struct gaih_servtuple -{ - struct gaih_servtuple *next; - int socktype; - int protocol; - int port; +struct gaih_service { + const char *name; + int num; }; -static const struct gaih_servtuple nullserv; - -struct gaih_addrtuple -{ - struct gaih_addrtuple *next; - int family; - char addr[16]; - uint32_t scopeid; +struct gaih_servtuple { + struct gaih_servtuple *next; + int socktype; + int protocol; + int port; }; -struct gaih_typeproto -{ - int socktype; - int protocol; - char name[4]; - int protoflag; +struct gaih_addrtuple { + struct gaih_addrtuple *next; + int family; + char addr[16]; + uint32_t scopeid; }; +struct gaih_typeproto { + socktype_t socktype; + protocol_t protocol; + int8_t protoflag; + char name[4]; +}; /* Values for `protoflag'. */ -#define GAI_PROTO_NOSERVICE 1 -#define GAI_PROTO_PROTOANY 2 - -static const struct gaih_typeproto gaih_inet_typeproto[] = -{ - { 0, 0, "", 0 }, - { SOCK_STREAM, IPPROTO_TCP, "tcp", 0 }, - { SOCK_DGRAM, IPPROTO_UDP, "udp", 0 }, - { SOCK_RAW, 0, "raw", GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE }, - { 0, 0, "", 0 } +#define GAI_PROTO_NOSERVICE 1 +#define GAI_PROTO_PROTOANY 2 + +static const struct gaih_typeproto gaih_inet_typeproto[] = { + { 0 , 0 , 0, "" }, + { SOCK_STREAM, IPPROTO_TCP, 0, "tcp" }, + { SOCK_DGRAM , IPPROTO_UDP, 0, "udp" }, + { SOCK_RAW , 0 , GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, "raw" }, + { 0 , 0 , 0, "" }, }; -struct gaih -{ - int family; - int (*gaih)(const char *name, const struct gaih_service *service, - const struct addrinfo *req, struct addrinfo **pai); +struct gaih { + int family; + int (*gaih)(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai); }; -#if PF_UNSPEC == 0 -static const struct addrinfo default_hints; -#else -static const struct addrinfo default_hints = -{ 0, PF_UNSPEC, 0, 0, 0, NULL, NULL, NULL }; -#endif - #define SEEN_IPV4 1 #define SEEN_IPV6 2 -static unsigned __check_pf (void) +static unsigned __check_pf(void) { - unsigned seen = 0; + unsigned seen = 0; + #if defined __UCLIBC_SUPPORT_AI_ADDRCONFIG__ - { - /* Get the interface list via getifaddrs. */ - struct ifaddrs *ifa = NULL; - struct ifaddrs *runp; - if (getifaddrs (&ifa) != 0) - { - /* We cannot determine what interfaces are available. Be - optimistic. */ + + struct ifaddrs *ifa; + struct ifaddrs *runp; + + /* Get the interface list via getifaddrs. */ + if (getifaddrs(&ifa) != 0) { + /* We cannot determine what interfaces are available. + * Be optimistic. */ #if defined __UCLIBC_HAS_IPV4__ - seen |= SEEN_IPV4; -#endif /* __UCLIBC_HAS_IPV4__ */ + seen |= SEEN_IPV4; +#endif #if defined __UCLIBC_HAS_IPV6__ - seen |= SEEN_IPV6; -#endif /* __UCLIBC_HAS_IPV6__ */ - return seen; - } + seen |= SEEN_IPV6; +#endif + return seen; + } - for (runp = ifa; runp != NULL; runp = runp->ifa_next) + for (runp = ifa; runp != NULL; runp = runp->ifa_next) { + if (runp->ifa_addr == NULL) + continue; #if defined __UCLIBC_HAS_IPV4__ - if (runp->ifa_addr->sa_family == PF_INET) - seen |= SEEN_IPV4; -#endif /* __UCLIBC_HAS_IPV4__ */ -#if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ - else /* can't be both at once */ -#endif /* __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ */ + if (runp->ifa_addr->sa_family == PF_INET) + seen |= SEEN_IPV4; +#endif #if defined __UCLIBC_HAS_IPV6__ - if (runp->ifa_addr->sa_family == PF_INET6) - seen |= SEEN_IPV6; -#endif /* __UCLIBC_HAS_IPV6__ */ + if (runp->ifa_addr->sa_family == PF_INET6) + seen |= SEEN_IPV6; +#endif + } + freeifaddrs(ifa); - (void) freeifaddrs (ifa); - } #else - /* AI_ADDRCONFIG is disabled, assume both ipv4 and ipv6 available. */ + + /* AI_ADDRCONFIG is disabled, assume both ipv4 and ipv6 available. */ #if defined __UCLIBC_HAS_IPV4__ - seen |= SEEN_IPV4; -#endif /* __UCLIBC_HAS_IPV4__ */ + seen |= SEEN_IPV4; +#endif #if defined __UCLIBC_HAS_IPV6__ - seen |= SEEN_IPV6; -#endif /* __UCLIBC_HAS_IPV6__ */ + seen |= SEEN_IPV6; +#endif #endif /* __UCLIBC_SUPPORT_AI_ADDRCONFIG__ */ - return seen; + + return seen; } -static int addrconfig (sa_family_t af) +static int addrconfig(sa_family_t af) { - int s; - int ret; - int saved_errno = errno; - unsigned seen; + int s; + int ret; + int saved_errno = errno; + unsigned seen; - seen = __check_pf(); + seen = __check_pf(); #if defined __UCLIBC_HAS_IPV4__ - if (af == AF_INET) - ret = seen & SEEN_IPV4; - else + if (af == AF_INET) + ret = seen & SEEN_IPV4; + else #endif #if defined __UCLIBC_HAS_IPV6__ - if (af == AF_INET6) - ret = seen & SEEN_IPV6; - else + if (af == AF_INET6) + ret = seen & SEEN_IPV6; + else #endif - { - s = socket(af, SOCK_DGRAM, 0); - ret = 1; /* Assume PF_UNIX. */ - if (s < 0) { - if (errno != EMFILE) - ret = 0; + { + s = socket(af, SOCK_DGRAM, 0); + ret = 1; /* Assume PF_UNIX. */ + if (s < 0) { + if (errno != EMFILE) + ret = 0; + } else + close(s); } - else - close(s); - } - __set_errno (saved_errno); - return ret; + __set_errno(saved_errno); + return ret; } #if 0 /* Using Unix sockets this way is a security risk. */ static int -gaih_local (const char *name, const struct gaih_service *service, - const struct addrinfo *req, struct addrinfo **pai) +gaih_local(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai) { - struct utsname utsname; - - if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST)) - return GAIH_OKIFUNSPEC | -EAI_NONAME; - - if ((name != NULL) || (req->ai_flags & AI_CANONNAME)) - if (uname (&utsname) < 0) - return -EAI_SYSTEM; - - if (name != NULL) - { - if (strcmp(name, "localhost") && - strcmp(name, "local") && - strcmp(name, "unix") && - strcmp(name, utsname.nodename)) - return GAIH_OKIFUNSPEC | -EAI_NONAME; - } - - if (req->ai_protocol || req->ai_socktype) - { - const struct gaih_typeproto *tp = gaih_inet_typeproto + 1; - - while (tp->name[0] - && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0 - || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype) - || (req->ai_protocol != 0 - && !(tp->protoflag & GAI_PROTO_PROTOANY) - && req->ai_protocol != tp->protocol))) - ++tp; - - if (! tp->name[0]) - { - if (req->ai_socktype) - return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); - else - return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + struct utsname utsname; + struct addrinfo *ai = *pai; + + if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST)) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + + if ((name != NULL) || (req->ai_flags & AI_CANONNAME)) + if (uname(&utsname) < 0) + return -EAI_SYSTEM; + + if (name != NULL) { + if (strcmp(name, "localhost") && + strcmp(name, "local") && + strcmp(name, "unix") && + strcmp(name, utsname.nodename)) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + } + + if (req->ai_protocol || req->ai_socktype) { + const struct gaih_typeproto *tp = gaih_inet_typeproto + 1; + + while (tp->name[0] + && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0 + || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype) + || (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol)) + ) { + ++tp; + } + if (! tp->name[0]) { + if (req->ai_socktype) + return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + } } - } - - *pai = malloc (sizeof (struct addrinfo) + sizeof (struct sockaddr_un) - + ((req->ai_flags & AI_CANONNAME) - ? (strlen(utsname.nodename) + 1): 0)); - if (*pai == NULL) - return -EAI_MEMORY; - - (*pai)->ai_next = NULL; - (*pai)->ai_flags = req->ai_flags; - (*pai)->ai_family = AF_LOCAL; - (*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM; - (*pai)->ai_protocol = req->ai_protocol; - (*pai)->ai_addrlen = sizeof (struct sockaddr_un); - (*pai)->ai_addr = (void *) (*pai) + sizeof (struct addrinfo); - -#if SALEN - ((struct sockaddr_un *) (*pai)->ai_addr)->sun_len = - sizeof (struct sockaddr_un); -#endif /* SALEN */ - ((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL; - memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX); + *pai = ai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_un) + + ((req->ai_flags & AI_CANONNAME) + ? (strlen(utsname.nodename) + 1) : 0)); + if (ai == NULL) + return -EAI_MEMORY; + + ai->ai_next = NULL; + ai->ai_flags = req->ai_flags; + ai->ai_family = AF_LOCAL; + ai->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM; + ai->ai_protocol = req->ai_protocol; + ai->ai_addrlen = sizeof(struct sockaddr_un); + ai->ai_addr = (void *)ai + sizeof(struct addrinfo); +#if 0 /* SALEN */ + ((struct sockaddr_un *)ai->ai_addr)->sun_len = sizeof(struct sockaddr_un); +#endif /* SALEN */ - if (service) - { - struct sockaddr_un *sunp = (struct sockaddr_un *) (*pai)->ai_addr; + ((struct sockaddr_un *)ai->ai_addr)->sun_family = AF_LOCAL; + memset(((struct sockaddr_un *)ai->ai_addr)->sun_path, 0, UNIX_PATH_MAX); - if (strchr (service->name, '/') != NULL) - { - if (strlen (service->name) >= sizeof (sunp->sun_path)) - return GAIH_OKIFUNSPEC | -EAI_SERVICE; + if (service) { + struct sockaddr_un *sunp = (struct sockaddr_un *)ai->ai_addr; - strcpy (sunp->sun_path, service->name); + if (strchr(service->name, '/') != NULL) { + if (strlen(service->name) >= sizeof(sunp->sun_path)) + return GAIH_OKIFUNSPEC | -EAI_SERVICE; + strcpy(sunp->sun_path, service->name); + } else { + if (strlen(P_tmpdir "/") + 1 + strlen(service->name) >= sizeof(sunp->sun_path)) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + stpcpy(stpcpy(sunp->sun_path, P_tmpdir "/"), service->name); + } + } else { + /* This is a dangerous use of the interface since there is a time + window between the test for the file and the actual creation + (done by the caller) in which a file with the same name could + be created. */ + char *buf = ((struct sockaddr_un *)ai->ai_addr)->sun_path; + + if (__path_search(buf, L_tmpnam, NULL, NULL, 0) != 0 + || __gen_tempname(buf, __GT_NOCREATE, 0, 0) != 0 + ) { + return -EAI_SYSTEM; + } } - else - { - if (strlen (P_tmpdir "/") + 1 + strlen (service->name) >= - sizeof (sunp->sun_path)) - return GAIH_OKIFUNSPEC | -EAI_SERVICE; - stpcpy (stpcpy (sunp->sun_path, P_tmpdir "/"), service->name); - } - } - else - { - /* This is a dangerous use of the interface since there is a time - window between the test for the file and the actual creation - (done by the caller) in which a file with the same name could - be created. */ - char *buf = ((struct sockaddr_un *) (*pai)->ai_addr)->sun_path; - - if (__builtin_expect (__path_search (buf, L_tmpnam, NULL, NULL, 0), - 0) != 0 - || __builtin_expect (__gen_tempname (buf, __GT_NOCREATE), 0) != 0) - return -EAI_SYSTEM; - } - - if (req->ai_flags & AI_CANONNAME) - (*pai)->ai_canonname = strcpy ((char *) *pai + sizeof (struct addrinfo) - + sizeof (struct sockaddr_un), - utsname.nodename); - else - (*pai)->ai_canonname = NULL; - return 0; + ai->ai_canonname = NULL; + if (req->ai_flags & AI_CANONNAME) + ai->ai_canonname = strcpy((char *)(ai + 1) + sizeof(struct sockaddr_un), + utsname.nodename); + return 0; } #endif /* 0 */ static int -gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, +gaih_inet_serv(const char *servicename, const struct gaih_typeproto *tp, const struct addrinfo *req, struct gaih_servtuple *st) { - struct servent *s; - size_t tmpbuflen = 1024; - struct servent ts; - char *tmpbuf; - int r; - - do - { - tmpbuf = alloca (tmpbuflen); - - r = getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen, - &s); - if (r != 0 || s == NULL) - { - if (r == ERANGE) + struct servent *s; + size_t tmpbuflen = 1024; + struct servent ts; + char *tmpbuf; + int r; + + while (1) { + tmpbuf = alloca(tmpbuflen); + r = getservbyname_r(servicename, tp->name, &ts, tmpbuf, tmpbuflen, &s); + if (r == 0 && s != NULL) + break; + if (r != ERANGE) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); tmpbuflen *= 2; - else - return GAIH_OKIFUNSPEC | -EAI_SERVICE; } - } - while (r); - - st->next = NULL; - st->socktype = tp->socktype; - st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) - ? req->ai_protocol : tp->protocol); - st->port = s->s_port; - - return 0; + st->next = NULL; + st->socktype = tp->socktype; + st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) ? req->ai_protocol : tp->protocol); + st->port = s->s_port; + return 0; } -#define gethosts(_family, _type) \ -{ \ - int i, herrno; \ - size_t tmpbuflen; \ - struct hostent th; \ - char *tmpbuf; \ - tmpbuflen = 512; \ - no_data = 0; \ - do { \ - tmpbuflen *= 2; \ - tmpbuf = alloca (tmpbuflen); \ - rc = gethostbyname2_r (name, _family, &th, tmpbuf, \ - tmpbuflen, &h, &herrno); \ - } while (rc == ERANGE && herrno == NETDB_INTERNAL); \ - if (rc != 0) \ - { \ - if (herrno == NETDB_INTERNAL) \ - { \ - __set_h_errno (herrno); \ - return -EAI_SYSTEM; \ - } \ - if (herrno == TRY_AGAIN) \ - no_data = EAI_AGAIN; \ - else \ - no_data = herrno == NO_DATA; \ - } \ - else if (h != NULL) \ - { \ - for (i = 0; h->h_addr_list[i]; i++) \ - { \ - if (*pat == NULL) { \ - *pat = alloca (sizeof(struct gaih_addrtuple)); \ - (*pat)->scopeid = 0; \ - } \ - (*pat)->next = NULL; \ - (*pat)->family = _family; \ - memcpy ((*pat)->addr, h->h_addr_list[i], \ - sizeof(_type)); \ - pat = &((*pat)->next); \ - } \ - } \ +#if defined __UCLIBC_HAS_IPV6__ +static uint8_t __gai_precedence = 0; /* =1 - IPv6, IPv4 + =2 - IPv4, IPv6 */ +#endif + +/* NB: also uses h,pat,rc,no_data variables */ +#define gethosts(_family, _type) \ +{ \ + int i, herrno; \ + size_t tmpbuflen; \ + struct hostent th; \ + char *tmpbuf; \ + \ + tmpbuflen = 512; \ + no_data = 0; \ + do { \ + tmpbuflen *= 2; \ + tmpbuf = alloca(tmpbuflen); \ + rc = gethostbyname2_r(name, _family, &th, tmpbuf, \ + tmpbuflen, &h, &herrno); \ + } while (rc == ERANGE && herrno == NETDB_INTERNAL); \ + if (rc != 0) { \ + if (herrno == NETDB_INTERNAL) { \ + __set_h_errno(herrno); \ + return -EAI_SYSTEM; \ + } \ + if (herrno == TRY_AGAIN) \ + no_data = EAI_AGAIN; \ + else \ + no_data = (herrno == NO_DATA); \ + } else if (h != NULL) { \ + for (i = 0; h->h_addr_list[i]; i++) { \ + if (*pat == NULL) { \ + *pat = alloca(sizeof(struct gaih_addrtuple)); \ + (*pat)->scopeid = 0; \ + } \ + (*pat)->next = NULL; \ + (*pat)->family = _family; \ + memcpy((*pat)->addr, h->h_addr_list[i], sizeof(_type)); \ + pat = &((*pat)->next); \ + } \ + } \ } static int -gaih_inet (const char *name, const struct gaih_service *service, - const struct addrinfo *req, struct addrinfo **pai) +gaih_inet(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai) { - const struct gaih_typeproto *tp = gaih_inet_typeproto; - struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv; - struct gaih_addrtuple *at = NULL; - int rc; - int v4mapped = (req->ai_family == PF_UNSPEC || req->ai_family == PF_INET6) && - (req->ai_flags & AI_V4MAPPED); - unsigned seen = __check_pf(); - - if (req->ai_protocol || req->ai_socktype) - { - ++tp; - - while (tp->name[0] - && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype) - || (req->ai_protocol != 0 - && !(tp->protoflag & GAI_PROTO_PROTOANY) - && req->ai_protocol != tp->protocol))) - ++tp; - - if (! tp->name[0]) - { - if (req->ai_socktype) - return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); - else - return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + struct gaih_servtuple nullserv; + + const struct gaih_typeproto *tp; + struct gaih_servtuple *st; + struct gaih_addrtuple *at; + int rc; + int v4mapped = req->ai_family == PF_INET6 && (req->ai_flags & AI_V4MAPPED); + unsigned seen = 0; + if (req->ai_flags & AI_ADDRCONFIG) { + /* "seen" is only used when AI_ADDRCONFIG is specified. + Avoid unnecessary call to __check_pf() otherwise + since it can be costly especially when RSBAC-Net is enabled. */ + seen = __check_pf(); } - } - if (service != NULL) - { - if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) - return (GAIH_OKIFUNSPEC | -EAI_SERVICE); - - if (service->num < 0) - { - if (tp->name[0]) - { - st = (struct gaih_servtuple *) - alloca (sizeof (struct gaih_servtuple)); - - if ((rc = gaih_inet_serv (service->name, tp, req, st))) - return rc; - } - else - { - struct gaih_servtuple **pst = &st; - for (tp++; tp->name[0]; tp++) - { - struct gaih_servtuple *newp; - - if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) - continue; - - if (req->ai_socktype != 0 - && req->ai_socktype != tp->socktype) - continue; - if (req->ai_protocol != 0 - && !(tp->protoflag & GAI_PROTO_PROTOANY) - && req->ai_protocol != tp->protocol) - continue; - - newp = (struct gaih_servtuple *) - alloca (sizeof (struct gaih_servtuple)); - - if ((rc = gaih_inet_serv (service->name, tp, req, newp))) - { - if (rc & GAIH_OKIFUNSPEC) - continue; - return rc; - } - - *pst = newp; - pst = &(newp->next); + memset(&nullserv, 0, sizeof(nullserv)); + + tp = gaih_inet_typeproto; + if (req->ai_protocol || req->ai_socktype) { + ++tp; + while (tp->name[0]) { + if ((req->ai_socktype == 0 || req->ai_socktype == tp->socktype) + && (req->ai_protocol == 0 || req->ai_protocol == tp->protocol || (tp->protoflag & GAI_PROTO_PROTOANY)) + ) { + goto found; + } + ++tp; } - if (st == (struct gaih_servtuple *) &nullserv) - return (GAIH_OKIFUNSPEC | -EAI_SERVICE); - } - } - else - { - st = alloca (sizeof (struct gaih_servtuple)); - st->next = NULL; - st->socktype = tp->socktype; - st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) - ? req->ai_protocol : tp->protocol); - st->port = htons (service->num); + if (req->ai_socktype) + return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + found: ; } - } - else if (req->ai_socktype || req->ai_protocol) - { - st = alloca (sizeof (struct gaih_servtuple)); - st->next = NULL; - st->socktype = tp->socktype; - st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) - ? req->ai_protocol : tp->protocol); - st->port = 0; - } - else - { - /* - * Neither socket type nor protocol is set. Return all socket types - * we know about. - */ - struct gaih_servtuple **lastp = &st; - for (++tp; tp->name[0]; ++tp) - { - struct gaih_servtuple *newp; - - newp = alloca (sizeof (struct gaih_servtuple)); - newp->next = NULL; - newp->socktype = tp->socktype; - newp->protocol = tp->protocol; - newp->port = 0; - *lastp = newp; - lastp = &newp->next; + st = &nullserv; + if (service != NULL) { + if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + + if (service->num < 0) { + if (tp->name[0]) { + st = alloca(sizeof(struct gaih_servtuple)); + rc = gaih_inet_serv(service->name, tp, req, st); + if (rc) + return rc; + } else { + struct gaih_servtuple **pst = &st; + for (tp++; tp->name[0]; tp++) { + struct gaih_servtuple *newp; + + if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) + continue; + + if (req->ai_socktype != 0 && req->ai_socktype != tp->socktype) + continue; + if (req->ai_protocol != 0 + && !(tp->protoflag & GAI_PROTO_PROTOANY) + && req->ai_protocol != tp->protocol) + continue; + + newp = alloca(sizeof(struct gaih_servtuple)); + rc = gaih_inet_serv(service->name, tp, req, newp); + if (rc) { + if (rc & GAIH_OKIFUNSPEC) + continue; + return rc; + } + + *pst = newp; + pst = &(newp->next); + } + if (st == &nullserv) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + } + } else { + st = alloca(sizeof(struct gaih_servtuple)); + st->next = NULL; + st->socktype = tp->socktype; + st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) + ? req->ai_protocol : tp->protocol); + st->port = htons(service->num); + } + } else if (req->ai_socktype || req->ai_protocol) { + st = alloca(sizeof(struct gaih_servtuple)); + st->next = NULL; + st->socktype = tp->socktype; + st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) + ? req->ai_protocol : tp->protocol); + st->port = 0; + } else { + /* + * Neither socket type nor protocol is set. Return all socket types + * we know about. + */ + struct gaih_servtuple **lastp = &st; + for (++tp; tp->name[0]; ++tp) { + struct gaih_servtuple *newp; + + newp = alloca(sizeof(struct gaih_servtuple)); + newp->next = NULL; + newp->socktype = tp->socktype; + newp->protocol = tp->protocol; + newp->port = 0; + + *lastp = newp; + lastp = &newp->next; + } } - } - - if (name != NULL) - { - at = alloca (sizeof (struct gaih_addrtuple)); - at->family = AF_UNSPEC; - at->scopeid = 0; - at->next = NULL; - - if (inet_pton (AF_INET, name, at->addr) > 0) - { - if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET || v4mapped) - at->family = AF_INET; - else - return -EAI_FAMILY; - } + at = NULL; + if (name != NULL) { + at = alloca(sizeof(struct gaih_addrtuple)); + at->family = AF_UNSPEC; + at->scopeid = 0; + at->next = NULL; + + if (inet_pton(AF_INET, name, at->addr) > 0) { + if (req->ai_family != AF_UNSPEC && req->ai_family != AF_INET && !v4mapped) + return -EAI_FAMILY; + at->family = AF_INET; + } #if defined __UCLIBC_HAS_IPV6__ - if (at->family == AF_UNSPEC) - { - char *namebuf = strdupa (name); - char *scope_delim; - - scope_delim = strchr (namebuf, SCOPE_DELIMITER); - if (scope_delim != NULL) - *scope_delim = '\0'; - - if (inet_pton (AF_INET6, namebuf, at->addr) > 0) - { - if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) - at->family = AF_INET6; - else - return -EAI_FAMILY; - - if (scope_delim != NULL) - { - int try_numericscope = 0; - if (IN6_IS_ADDR_LINKLOCAL (at->addr) - || IN6_IS_ADDR_MC_LINKLOCAL (at->addr)) - { - at->scopeid = if_nametoindex (scope_delim + 1); - if (at->scopeid == 0) - try_numericscope = 1; - } - else - try_numericscope = 1; - - if (try_numericscope != 0) - { - char *end; - assert (sizeof (uint32_t) <= sizeof (unsigned long)); - at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end, - 10); - if (*end != '\0') - return GAIH_OKIFUNSPEC | -EAI_NONAME; - } + if (at->family == AF_UNSPEC) { + char *namebuf = strdupa(name); + char *scope_delim; + + scope_delim = strchr(namebuf, SCOPE_DELIMITER); + if (scope_delim != NULL) + *scope_delim = '\0'; + + if (inet_pton(AF_INET6, namebuf, at->addr) > 0) { + if (req->ai_family != AF_UNSPEC && req->ai_family != AF_INET6) + return -EAI_FAMILY; + at->family = AF_INET6; + if (scope_delim != NULL) { + int try_numericscope = 0; + uint32_t *a32 = (uint32_t*)at->addr; + if (IN6_IS_ADDR_LINKLOCAL(a32) || IN6_IS_ADDR_MC_LINKLOCAL(at->addr)) { + at->scopeid = if_nametoindex(scope_delim + 1); + if (at->scopeid == 0) + try_numericscope = 1; + } else + try_numericscope = 1; + + if (try_numericscope != 0) { + char *end; + assert(sizeof(uint32_t) <= sizeof(unsigned long)); + at->scopeid = (uint32_t)strtoul(scope_delim + 1, &end, 10); + if (*end != '\0') + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + } + } + } } - } - } #endif - if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0) - { - struct hostent *h; - struct gaih_addrtuple **pat = &at; - int no_data = 0; - int no_inet6_data; - - /* - * If we are looking for both IPv4 and IPv6 address we don't want - * the lookup functions to automatically promote IPv4 addresses to - * IPv6 addresses. - */ - + if (at->family == AF_UNSPEC && !(req->ai_flags & AI_NUMERICHOST)) { + struct hostent *h; + struct gaih_addrtuple **pat = &at; + int no_data, no_inet6_data; #if defined __UCLIBC_HAS_IPV6__ - if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) - if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV6)) - gethosts (AF_INET6, struct in6_addr); + bool first_try = true; #endif - no_inet6_data = no_data; - - if (req->ai_family == AF_INET || - (!v4mapped && req->ai_family == AF_UNSPEC) || - (v4mapped && (no_inet6_data != 0 || (req->ai_flags & AI_ALL)))) - if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV4)) - gethosts (AF_INET, struct in_addr); - - if (no_data != 0 && no_inet6_data != 0) - { - /* If both requests timed out report this. */ - if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN) - return -EAI_AGAIN; - /* - * We made requests but they turned out no data. - * The name is known, though. - */ - return (GAIH_OKIFUNSPEC | -EAI_AGAIN); - } - } + /* + * If we are looking for both IPv4 and IPv6 address we don't want + * the lookup functions to automatically promote IPv4 addresses to + * IPv6 addresses. + */ + no_inet6_data = no_data = 0; +#if defined __UCLIBC_HAS_IPV6__ + if (__gai_precedence == 2) + goto try_v4; + + try_v6: + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) + if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV6)) + gethosts(AF_INET6, struct in6_addr); + no_inet6_data = no_data; + if (!first_try) + goto tried_all; + first_try = false; + + try_v4: +#endif + if (req->ai_family == AF_INET + || (!v4mapped && req->ai_family == AF_UNSPEC) + || (v4mapped && (no_inet6_data != 0 || (req->ai_flags & AI_ALL))) + ) { + if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV4)) + gethosts(AF_INET, struct in_addr); + } +#if defined __UCLIBC_HAS_IPV6__ + if (first_try) { + first_try = false; + goto try_v6; + } - if (at->family == AF_UNSPEC) - return (GAIH_OKIFUNSPEC | -EAI_NONAME); - } - else - { - struct gaih_addrtuple *atr; - atr = at = alloca (sizeof (struct gaih_addrtuple)); - memset (at, '\0', sizeof (struct gaih_addrtuple)); + tried_all: +#endif + if (no_data != 0 && no_inet6_data != 0) { + /* If both requests timed out report this. */ + if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN) + return -EAI_AGAIN; + /* + * We made requests but they turned out no data. + * The name is known, though. + */ + return (GAIH_OKIFUNSPEC | -EAI_AGAIN); + } + } - if (req->ai_family == 0) - { - at->next = alloca (sizeof (struct gaih_addrtuple)); - memset (at->next, '\0', sizeof (struct gaih_addrtuple)); - } + if (at->family == AF_UNSPEC) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + } else { + struct gaih_addrtuple *atr; + atr = at = alloca(sizeof(struct gaih_addrtuple)); + memset(at, '\0', sizeof(struct gaih_addrtuple)); + if (req->ai_family == 0) { + at->next = alloca(sizeof(struct gaih_addrtuple)); + memset(at->next, '\0', sizeof(struct gaih_addrtuple)); + } #if defined __UCLIBC_HAS_IPV6__ - if (req->ai_family == 0 || req->ai_family == AF_INET6) - { - at->family = AF_INET6; - if ((req->ai_flags & AI_PASSIVE) == 0) - memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr)); - atr = at->next; - } + if (req->ai_family == 0 || req->ai_family == AF_INET6) { + at->family = AF_INET6; + if ((req->ai_flags & AI_PASSIVE) == 0) + memcpy(at->addr, &in6addr_loopback, sizeof(struct in6_addr)); + atr = at->next; + } #endif - - if (req->ai_family == 0 || req->ai_family == AF_INET) - { - atr->family = AF_INET; - if ((req->ai_flags & AI_PASSIVE) == 0) - *(uint32_t *) atr->addr = htonl (INADDR_LOOPBACK); + if (req->ai_family == 0 || req->ai_family == AF_INET) { + atr->family = AF_INET; + if ((req->ai_flags & AI_PASSIVE) == 0) { + uint32_t *a = (uint32_t*)atr->addr; + *a = htonl(INADDR_LOOPBACK); + } + } } - } - if (pai == NULL) - return 0; - - { - const char *c = NULL; - struct gaih_servtuple *st2; - struct gaih_addrtuple *at2 = at; - size_t socklen, namelen; - sa_family_t family; - - /* - * buffer is the size of an unformatted IPv6 address in - * printable format. - */ - char buffer[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + if (pai == NULL) + return 0; - while (at2 != NULL) { - if (req->ai_flags & AI_CANONNAME) - { - struct hostent *h = NULL; - - int herrno; - struct hostent th; - size_t tmpbuflen = 512; - char *tmpbuf; - - do - { - tmpbuflen *= 2; - tmpbuf = alloca (tmpbuflen); - - if (tmpbuf == NULL) - return -EAI_MEMORY; - - rc = gethostbyaddr_r (at2->addr, - ((at2->family == AF_INET6) - ? sizeof(struct in6_addr) - : sizeof(struct in_addr)), - at2->family, &th, tmpbuf, tmpbuflen, - &h, &herrno); + const char *c = NULL; + struct gaih_servtuple *st2; + struct gaih_addrtuple *at2 = at; + size_t socklen, namelen; + sa_family_t family; - } - while (rc == errno && herrno == NETDB_INTERNAL); + /* + * buffer is the size of an unformatted IPv6 address in + * printable format. + */ + char buffer[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; + + while (at2 != NULL) { + c = inet_ntop(at2->family, at2->addr, buffer, sizeof(buffer)); + if (c) { + namelen = strlen(c) + 1; + } else if (req->ai_flags & AI_CANONNAME) { + struct hostent *h = NULL; + int herrno; + struct hostent th; + size_t tmpbuflen = 512; + char *tmpbuf; + + /* Hint says numeric, but address is not */ + if (req->ai_flags & AI_NUMERICHOST) + return -EAI_NONAME; + + do { + tmpbuflen *= 2; + tmpbuf = alloca(tmpbuflen); + rc = gethostbyaddr_r(at2->addr, +#ifdef __UCLIBC_HAS_IPV6__ + ((at2->family == AF_INET6) + ? sizeof(struct in6_addr) + : sizeof(struct in_addr)), +#else + sizeof(struct in_addr), +#endif + at2->family, + &th, tmpbuf, tmpbuflen, + &h, &herrno); + } while (rc == ERANGE && herrno == NETDB_INTERNAL); - if (rc != 0 && herrno == NETDB_INTERNAL) - { - __set_h_errno (herrno); - return -EAI_SYSTEM; - } + if (rc != 0 && herrno == NETDB_INTERNAL) { + __set_h_errno(herrno); + return -EAI_SYSTEM; + } - if (h == NULL) - c = inet_ntop (at2->family, at2->addr, buffer, sizeof(buffer)); - else - c = h->h_name; + if (h != NULL) + c = h->h_name; - if (c == NULL) - return GAIH_OKIFUNSPEC | -EAI_NONAME; + if (c == NULL) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); - namelen = strlen (c) + 1; - } - else - namelen = 0; + namelen = strlen(c) + 1; + } else + namelen = 0; #if defined __UCLIBC_HAS_IPV6__ - if (at2->family == AF_INET6 || v4mapped) - { - family = AF_INET6; - socklen = sizeof (struct sockaddr_in6); - } + if (at2->family == AF_INET6 || v4mapped) { + family = AF_INET6; + socklen = sizeof(struct sockaddr_in6); + } #endif #if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ - else + else #endif #if defined __UCLIBC_HAS_IPV4__ - { - family = AF_INET; - socklen = sizeof (struct sockaddr_in); - } + { + family = AF_INET; + socklen = sizeof(struct sockaddr_in); + } #endif - for (st2 = st; st2 != NULL; st2 = st2->next) - { - if (req->ai_flags & AI_ADDRCONFIG) { - if (family == AF_INET && !(seen & SEEN_IPV4)) - break; + for (st2 = st; st2 != NULL; st2 = st2->next) { + if (req->ai_flags & AI_ADDRCONFIG) { + if (family == AF_INET && !(seen & SEEN_IPV4)) + break; #if defined __UCLIBC_HAS_IPV6__ - else if (family == AF_INET6 && !(seen & SEEN_IPV6)) - break; + else if (family == AF_INET6 && !(seen & SEEN_IPV6)) + break; #endif - } - *pai = malloc (sizeof (struct addrinfo) + socklen + namelen); - if (*pai == NULL) - return -EAI_MEMORY; - - (*pai)->ai_flags = req->ai_flags; - (*pai)->ai_family = family; - (*pai)->ai_socktype = st2->socktype; - (*pai)->ai_protocol = st2->protocol; - (*pai)->ai_addrlen = socklen; - (*pai)->ai_addr = (void *) (*pai) + sizeof(struct addrinfo); -#if SALEN - (*pai)->ai_addr->sa_len = socklen; -#endif /* SALEN */ - (*pai)->ai_addr->sa_family = family; + } + *pai = malloc(sizeof(struct addrinfo) + socklen + namelen); + if (*pai == NULL) + return -EAI_MEMORY; + + (*pai)->ai_flags = req->ai_flags; + (*pai)->ai_family = family; + (*pai)->ai_socktype = st2->socktype; + (*pai)->ai_protocol = st2->protocol; + (*pai)->ai_addrlen = socklen; + (*pai)->ai_addr = (void *) (*pai) + sizeof(struct addrinfo); +#if 0 /* SALEN */ + (*pai)->ai_addr->sa_len = socklen; +#endif + (*pai)->ai_addr->sa_family = family; #if defined __UCLIBC_HAS_IPV6__ - if (family == AF_INET6) - { - struct sockaddr_in6 *sin6p = - (struct sockaddr_in6 *) (*pai)->ai_addr; - - sin6p->sin6_flowinfo = 0; - if (at2->family == AF_INET6) - { - memcpy (&sin6p->sin6_addr, - at2->addr, sizeof (struct in6_addr)); - } - else - { - sin6p->sin6_addr.s6_addr32[0] = 0; - sin6p->sin6_addr.s6_addr32[1] = 0; - sin6p->sin6_addr.s6_addr32[2] = htonl(0x0000ffff); - memcpy(&sin6p->sin6_addr.s6_addr32[3], - at2->addr, sizeof (sin6p->sin6_addr.s6_addr32[3])); - } - sin6p->sin6_port = st2->port; - sin6p->sin6_scope_id = at2->scopeid; - } + if (family == AF_INET6) { + struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *) (*pai)->ai_addr; + + sin6p->sin6_flowinfo = 0; + if (at2->family == AF_INET6) { + memcpy(&sin6p->sin6_addr, + at2->addr, sizeof(struct in6_addr)); + } else { + sin6p->sin6_addr.s6_addr32[0] = 0; + sin6p->sin6_addr.s6_addr32[1] = 0; + sin6p->sin6_addr.s6_addr32[2] = htonl(0x0000ffff); + memcpy(&sin6p->sin6_addr.s6_addr32[3], + at2->addr, sizeof(sin6p->sin6_addr.s6_addr32[3])); + } + sin6p->sin6_port = st2->port; + sin6p->sin6_scope_id = at2->scopeid; + } #endif #if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ - else + else #endif #if defined __UCLIBC_HAS_IPV4__ - { - struct sockaddr_in *sinp = - (struct sockaddr_in *) (*pai)->ai_addr; - - memcpy (&sinp->sin_addr, - at2->addr, sizeof (struct in_addr)); - sinp->sin_port = st2->port; - memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero)); - } + { + struct sockaddr_in *sinp = (struct sockaddr_in *) (*pai)->ai_addr; + + memcpy(&sinp->sin_addr, at2->addr, sizeof(struct in_addr)); + sinp->sin_port = st2->port; + memset(sinp->sin_zero, '\0', sizeof(sinp->sin_zero)); + } #endif - if (c) - { - (*pai)->ai_canonname = ((void *) (*pai) + - sizeof (struct addrinfo) + socklen); - strcpy ((*pai)->ai_canonname, c); + if (c) { + (*pai)->ai_canonname = ((void *) (*pai) + + sizeof(struct addrinfo) + socklen); + strcpy((*pai)->ai_canonname, c); + } else { + (*pai)->ai_canonname = NULL; + } + (*pai)->ai_next = NULL; + pai = &((*pai)->ai_next); + } + + at2 = at2->next; } - else - (*pai)->ai_canonname = NULL; - - (*pai)->ai_next = NULL; - pai = &((*pai)->ai_next); - } - - at2 = at2->next; } - } - return 0; + return 0; } -static struct gaih gaih[] = -{ +static const struct gaih gaih[] = { #if defined __UCLIBC_HAS_IPV6__ - { PF_INET6, gaih_inet }, + { PF_INET6, gaih_inet }, #endif - { PF_INET, gaih_inet }, + { PF_INET, gaih_inet }, #if 0 - { PF_LOCAL, gaih_local }, + { PF_LOCAL, gaih_local }, #endif - { PF_UNSPEC, NULL } + { PF_UNSPEC, NULL } }; -libc_hidden_proto(freeaddrinfo) +#if defined __UCLIBC_HAS_IPV6__ + +/* + * A call to getaddrinfo might return multiple answers. To provide + * possibility to change the sorting we must use /etc/gai.conf file, + * like glibc. + * + * gai.conf format: + * + * label <netmask> <precedence> + * The value is added to the label table used in + * the RFC 3484 sorting. If any label definition + * is present in the configuration file is present, + * the default table is not used. All the label + * definitions of the default table which are to + * be maintained have to be duplicated. + * precedence <netmask> <precedence> + * This keyword is similar to label, but instead + * the value is added to the precedence table as + * specified in RFC 3484. Once again, the presence + * of a single precedence line in the configuration + * file causes the default table to not be used. + * + * The simplified uclibc's implementation allows to change the IPv4/IPv6 + * sorting order for a whole address space only, i.e + * "precedence ::ffff:0:0/96 100" is only supported. + */ +static void __gai_conf_parse(void) +{ + /* NO reread of /etc/gai.conf on change. */ + if (__gai_precedence != 0) + return; + + __gai_precedence = 1; /* default IPv6 */ + + parser_t *parser; + char **tok = NULL; + + parser = config_open("/etc/gai.conf"); + if (!parser) + return; + + while (config_read(parser, &tok, 3, 3, "# \t", PARSE_NORMAL)) { + if (strcmp(tok[0], "precedence") == 0) { + char *pfx; + struct in6_addr mask; + + pfx = strchr(tok[1], '/'); + if (!pfx) + continue; + *(pfx++) = 0; + if (inet_pton(AF_INET6, tok[1], &mask) <= 0) + continue; + if (IN6_IS_ADDR_V4MAPPED(&mask) + && mask.s6_addr32[3] == 0 + && atoi(pfx) == 96 && atoi(tok[2]) == 100) + __gai_precedence = 2; /* IPv4 first */ + } + } + config_close(parser); +} +#else +# define __gai_conf_parse(x) +#endif /* __UCLIBC_HAS_IPV6__ */ + void -freeaddrinfo (struct addrinfo *ai) +freeaddrinfo(struct addrinfo *ai) { - struct addrinfo *p; - - while (ai != NULL) - { - p = ai; - ai = ai->ai_next; - free (p); - } + struct addrinfo *p; + + while (ai != NULL) { + p = ai; + ai = ai->ai_next; + free(p); + } } libc_hidden_def(freeaddrinfo) -libc_hidden_proto(getaddrinfo) int -getaddrinfo (const char *name, const char *service, +getaddrinfo(const char *name, const char *service, const struct addrinfo *hints, struct addrinfo **pai) { - int i = 0, j = 0, last_i = 0; - struct addrinfo *p = NULL, **end; - struct gaih *g = gaih, *pg = NULL; - struct gaih_service gaih_service, *pservice; - - if (name != NULL && name[0] == '*' && name[1] == 0) - name = NULL; - - if (service != NULL && service[0] == '*' && service[1] == 0) - service = NULL; - - if (name == NULL && service == NULL) - return EAI_NONAME; - - if (hints == NULL) - hints = &default_hints; - - if (hints->ai_flags & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST| - AI_ADDRCONFIG|AI_V4MAPPED|AI_NUMERICSERV|AI_ALL)) - return EAI_BADFLAGS; - - if ((hints->ai_flags & AI_CANONNAME) && name == NULL) - return EAI_BADFLAGS; - - if (service && service[0]) - { - char *c; - gaih_service.name = service; - gaih_service.num = strtoul (gaih_service.name, &c, 10); - if (*c != '\0') { - if (hints->ai_flags & AI_NUMERICSERV) - return EAI_NONAME; - - gaih_service.num = -1; + int i, j, last_i; + struct addrinfo *p, **end; + const struct gaih *g, *pg; + struct gaih_service gaih_service, *pservice; + struct addrinfo default_hints; + + if (name != NULL && name[0] == '*' && name[1] == 0) + name = NULL; + + if (service != NULL && service[0] == '*' && service[1] == 0) + service = NULL; + + if (name == NULL && service == NULL) + return EAI_NONAME; + + if (hints == NULL) { + memset(&default_hints, 0, sizeof(default_hints)); + if (AF_UNSPEC != 0) + default_hints.ai_family = AF_UNSPEC; + hints = &default_hints; } - else - /* - * Can't specify a numerical socket unless a protocol - * family was given. - */ - if (hints->ai_socktype == 0 && hints->ai_protocol == 0) - return EAI_SERVICE; - pservice = &gaih_service; - } - else - pservice = NULL; - - if (pai) - end = &p; - else - end = NULL; - while (g->gaih) - { - if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC) - { - if ((hints->ai_flags & AI_ADDRCONFIG) && !addrconfig(g->family)) - { - ++g; - continue; - } - j++; - if (pg == NULL || pg->gaih != g->gaih) - { - pg = g; - i = g->gaih (name, pservice, hints, end); - if (i != 0) - { - last_i = i; - - if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC)) - continue; - - if (p) - freeaddrinfo (p); - - return -(i & GAIH_EAI); + if (hints->ai_flags & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST| + AI_ADDRCONFIG|AI_V4MAPPED|AI_NUMERICSERV|AI_ALL)) + return EAI_BADFLAGS; + + if ((hints->ai_flags & AI_CANONNAME) && name == NULL) + return EAI_BADFLAGS; + + if (service && service[0]) { + char *c; + gaih_service.name = service; + gaih_service.num = strtoul(gaih_service.name, &c, 10); + if (*c != '\0') { + if (hints->ai_flags & AI_NUMERICSERV) + return EAI_NONAME; + gaih_service.num = -1; + } + pservice = &gaih_service; + } else + pservice = NULL; + + __gai_conf_parse(); + g = gaih; + pg = NULL; + p = NULL; + end = NULL; + if (pai) + end = &p; + i = 0; + last_i = 0; + j = 0; + while (g->gaih) { + if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC) { + if ((hints->ai_flags & AI_ADDRCONFIG) && !addrconfig(g->family)) { + ++g; + continue; + } + j++; + if (pg == NULL || pg->gaih != g->gaih) { + pg = g; + i = g->gaih(name, pservice, hints, end); + if (i != 0) { + last_i = i; + if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC)) + continue; + /*if (p) - freeaddrinfo works ok on NULL too */ + freeaddrinfo(p); + return -(i & GAIH_EAI); + } + if (end) + while (*end) + end = &((*end)->ai_next); + } } - if (end) - while(*end) end = &((*end)->ai_next); - } + ++g; } - ++g; - } - if (j == 0) - return EAI_FAMILY; + if (j == 0) + return EAI_FAMILY; - if (p) - { - *pai = p; - return 0; - } + if (p) { + *pai = p; + return 0; + } - if (pai == NULL && last_i == 0) - return 0; + if (pai == NULL && last_i == 0) + return 0; - if (p) - freeaddrinfo (p); + /* if (p) - never happens, see above */ + /* freeaddrinfo(p); */ - return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME; + return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME; } libc_hidden_def(getaddrinfo) diff --git a/libc/inet/gethostbyaddr.c b/libc/inet/gethostbyaddr.c index ae8a543e5..dc16dd9eb 100644 --- a/libc/inet/gethostbyaddr.c +++ b/libc/inet/gethostbyaddr.c @@ -5,4 +5,4 @@ */ #define L_gethostbyaddr -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/gethostbyaddr_r.c b/libc/inet/gethostbyaddr_r.c index 6235c82e1..6e27e6207 100644 --- a/libc/inet/gethostbyaddr_r.c +++ b/libc/inet/gethostbyaddr_r.c @@ -5,4 +5,4 @@ */ #define L_gethostbyaddr_r -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/gethostbyname.c b/libc/inet/gethostbyname.c index 3d46ab015..9c9e9ca03 100644 --- a/libc/inet/gethostbyname.c +++ b/libc/inet/gethostbyname.c @@ -5,4 +5,4 @@ */ #define L_gethostbyname -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/gethostbyname2.c b/libc/inet/gethostbyname2.c index 685801642..5b9e74ba0 100644 --- a/libc/inet/gethostbyname2.c +++ b/libc/inet/gethostbyname2.c @@ -5,4 +5,4 @@ */ #define L_gethostbyname2 -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/gethostbyname2_r.c b/libc/inet/gethostbyname2_r.c index 06d058ae7..0de0dd5e1 100644 --- a/libc/inet/gethostbyname2_r.c +++ b/libc/inet/gethostbyname2_r.c @@ -5,4 +5,4 @@ */ #define L_gethostbyname2_r -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/gethostbyname_r.c b/libc/inet/gethostbyname_r.c index fc9e56da5..4b34f8d17 100644 --- a/libc/inet/gethostbyname_r.c +++ b/libc/inet/gethostbyname_r.c @@ -5,4 +5,4 @@ */ #define L_gethostbyname_r -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/gethostent.c b/libc/inet/gethostent.c index 16133c0e4..64c183177 100644 --- a/libc/inet/gethostent.c +++ b/libc/inet/gethostent.c @@ -5,4 +5,4 @@ */ #define L_gethostent -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/resolvename.c b/libc/inet/gethostent_r.c index 157878fd1..48225d7fa 100644 --- a/libc/inet/resolvename.c +++ b/libc/inet/gethostent_r.c @@ -4,5 +4,5 @@ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ -#define L_resolvename -#include "resolv.c" +#define L_gethostent_r +#include RESOLVER diff --git a/libc/inet/getnameinfo.c b/libc/inet/getnameinfo.c index fbfd3ede1..86edc51f3 100644 --- a/libc/inet/getnameinfo.c +++ b/libc/inet/getnameinfo.c @@ -5,4 +5,4 @@ */ #define L_getnameinfo -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/getnet.c b/libc/inet/getnet.c new file mode 100644 index 000000000..9049f97af --- /dev/null +++ b/libc/inet/getnet.c @@ -0,0 +1,208 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org> + * + * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +/* /etc/networks +# network-name number [aliases ...] +loopback 127.0.0.0 # optional aliases + +network-name: symbolic name of the netwkork +number: official number of the network in dotted quad +aliases: case sensitive optional space or tab separated list of other names +*/ + +#include <features.h> +#include <netdb.h> +#include <string.h> +#include <stdlib.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> +#include <unistd.h> +#include "internal/parse_config.h" + +#include <bits/uClibc_mutex.h> +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +#define MINTOKENS 2 +#define MAXALIASES 8 +#define MAXTOKENS (MINTOKENS + MAXALIASES + 1) +#define BUFSZ (255) /* one line */ +#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS)) + +static parser_t *netp = NULL; +static struct netent nete; +static char *netbuf = NULL; +static smallint net_stayopen; + +void setnetent(int stayopen) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (netp) + config_close(netp); + netp = config_open(_PATH_NETWORKS); + if (stayopen) + net_stayopen = 1; + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(setnetent) + +void endnetent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (netp) { + config_close(netp); + netp = NULL; + } + net_stayopen = 0; + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(endnetent) + +int getnetent_r(struct netent *result_buf, + char *buf, size_t buflen, struct netent **result, + int *h_errnop + ) +{ + char **tok = NULL; + const size_t aliaslen = sizeof(char *) * MAXTOKENS; + int ret = ERANGE; + + *result = NULL; + if (buflen < aliaslen + || (buflen - aliaslen) < BUFSZ + 1) + goto DONE_NOUNLOCK; + + __UCLIBC_MUTEX_LOCK(mylock); + ret = ENOENT; + if (netp == NULL) + setnetent(net_stayopen); + if (netp == NULL) + goto DONE; + netp->data = buf; + netp->data_len = aliaslen; + netp->line_len = buflen - aliaslen; + /* <name>[[:space:]]<netnumber>[[:space:]][<aliases>] */ + if (!config_read(netp, &tok, MAXTOKENS-1, MINTOKENS, "# \t/", PARSE_NORMAL)) { + goto DONE; + } + result_buf->n_name = *(tok++); + { + struct addrinfo hints, *addri; +# define sa4_to_uint32(sa) \ + (ntohl(((struct sockaddr_in*)sa)->sin_addr.s_addr)) +#ifdef __UCLIBC_HAS_IPV6__ +# define sa6_to_uint8(sa) \ + (ntohl(((struct sockaddr_in6*)sa)->sin6_addr.s6_addr)) +#endif + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_NUMERICHOST; + getaddrinfo(*(tok++), NULL, &hints, &addri); + result_buf->n_addrtype = addri->ai_family; + result_buf->n_net = +#if 0 /*FIXME: implement me! def __UCLIBC_HAS_IPV6__ */ + addri->ai_family == AF_INET6 ? sa6_to_uint8(addri->ai_addr) : +#endif + sa4_to_uint32(addri->ai_addr); + freeaddrinfo(addri); + } + result_buf->n_aliases = tok; + *result = result_buf; + ret = 0; + DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + DONE_NOUNLOCK: + errno = ret; + return errno; +} +libc_hidden_def(getnetent_r) + +static void __initbuf(void) +{ + if (!netbuf) { + netbuf = malloc(SBUFSIZE); + if (!netbuf) + abort(); + } +} + +struct netent *getnetent(void) +{ + struct netent *result; + int herrnop; + + __initbuf(); + getnetent_r(&nete, netbuf, SBUFSIZE, &result, &herrnop); + return result; +} + +int getnetbyname_r(const char *name, + struct netent *result_buf, char *buf, size_t buflen, + struct netent **result, + int *h_errnop + ) +{ + register char **cp; + int ret, herrnop; + + __UCLIBC_MUTEX_LOCK(mylock); + setnetent(net_stayopen); + while (!(ret = getnetent_r(result_buf, buf, buflen, result, &herrnop))) { + if (strcmp(name, result_buf->n_name) == 0) + break; + for (cp = result_buf->n_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + } + gotname: + if (!net_stayopen) + endnetent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; +} +libc_hidden_def(getnetbyname_r) + +struct netent *getnetbyname(const char *name) +{ + struct netent *result; + int herrnop; + + __initbuf(); + getnetbyname_r(name, &nete, netbuf, SBUFSIZE, &result, &herrnop); + return result; +} + +int getnetbyaddr_r(uint32_t net, int type, + struct netent *result_buf, char *buf, + size_t buflen, struct netent **result, + int *h_errnop) +{ + int ret, herrnop; + + __UCLIBC_MUTEX_LOCK(mylock); + setnetent(net_stayopen); + while (!(ret = getnetent_r(result_buf, buf, buflen, result, &herrnop))) { + if (net == result_buf->n_net && type == result_buf->n_addrtype) + break; + } + if (!net_stayopen) + endnetent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; +} +libc_hidden_def(getnetbyaddr_r) + +struct netent *getnetbyaddr(uint32_t net, int type) +{ + struct netent *result; + int herrnop; + + __initbuf(); + getnetbyaddr_r(net, type, &nete, netbuf, SBUFSIZE, &result, &herrnop); + return result; +} + diff --git a/libc/inet/getnetbyad.c b/libc/inet/getnetbyad.c deleted file mode 100644 index c916a18cf..000000000 --- a/libc/inet/getnetbyad.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#define __FORCE_GLIBC -#include <features.h> -#include <netdb.h> -#include <unistd.h> - -libc_hidden_proto(setnetent) -libc_hidden_proto(getnetent) -libc_hidden_proto(endnetent) - -extern smallint _net_stayopen attribute_hidden; - -struct netent *getnetbyaddr (uint32_t net, int type) -{ - register struct netent *p; - - setnetent(_net_stayopen); - while ((p = getnetent())) - if (p->n_addrtype == type && p->n_net == net) - break; - if (!_net_stayopen) - endnetent(); - return (p); -} diff --git a/libc/inet/getnetbynm.c b/libc/inet/getnetbynm.c deleted file mode 100644 index 9f3655121..000000000 --- a/libc/inet/getnetbynm.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#define __FORCE_GLIBC -#include <features.h> -#include <netdb.h> -#include <string.h> -#include <unistd.h> - -/* Experimentally off - libc_hidden_proto(strcmp) */ -libc_hidden_proto(setnetent) -libc_hidden_proto(getnetent) -libc_hidden_proto(endnetent) - -extern smallint _net_stayopen attribute_hidden; - -struct netent * -getnetbyname(const char *name) -{ - register struct netent *p; - register char **cp; - - setnetent(_net_stayopen); - while ((p = getnetent())) { - if (strcmp(p->n_name, name) == 0) - break; - for (cp = p->n_aliases; *cp != 0; cp++) - if (strcmp(*cp, name) == 0) - goto found; - } -found: - if (!_net_stayopen) - endnetent(); - return (p); -} diff --git a/libc/inet/getnetent.c b/libc/inet/getnetent.c deleted file mode 100644 index 863266d48..000000000 --- a/libc/inet/getnetent.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#define __FORCE_GLIBC -#include <features.h> -#include <stdio.h> -#include <stdlib.h> -#include <netdb.h> -#include <arpa/inet.h> -#include <unistd.h> - -libc_hidden_proto(fopen) -libc_hidden_proto(fclose) -libc_hidden_proto(inet_network) -libc_hidden_proto(rewind) -libc_hidden_proto(fgets) -libc_hidden_proto(abort) - -#include <bits/uClibc_mutex.h> -__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); - - - -#define MAXALIASES 35 -static const char NETDB[] = _PATH_NETWORKS; -static FILE *netf = NULL; -static char *line = NULL; -static struct netent net; -static char *net_aliases[MAXALIASES]; - -smallint _net_stayopen attribute_hidden; - -libc_hidden_proto(setnetent) -void setnetent(int f) -{ - __UCLIBC_MUTEX_LOCK(mylock); - if (netf == NULL) - netf = fopen(NETDB, "r" ); - else - rewind(netf); - if (f) _net_stayopen = 1; - __UCLIBC_MUTEX_UNLOCK(mylock); - return; -} -libc_hidden_def(setnetent) - -libc_hidden_proto(endnetent) -void endnetent(void) -{ - __UCLIBC_MUTEX_LOCK(mylock); - if (netf) { - fclose(netf); - netf = NULL; - } - _net_stayopen = 0; - __UCLIBC_MUTEX_UNLOCK(mylock); -} -libc_hidden_def(endnetent) - -static char * any(register char *cp, char *match) -{ - register char *mp, c; - - while ((c = *cp)) { - for (mp = match; *mp; mp++) - if (*mp == c) - return (cp); - cp++; - } - return ((char *)0); -} - -libc_hidden_proto(getnetent) -struct netent *getnetent(void) -{ - char *p; - register char *cp, **q; - struct netent *rv = NULL; - - __UCLIBC_MUTEX_LOCK(mylock); - if (netf == NULL && (netf = fopen(NETDB, "r" )) == NULL) { - goto DONE; - } -again: - - if (!line) { - line = malloc(BUFSIZ + 1); - if (!line) - abort(); - } - - p = fgets(line, BUFSIZ, netf); - if (p == NULL) { - goto DONE; - } - if (*p == '#') - goto again; - cp = any(p, "#\n"); - if (cp == NULL) - goto again; - *cp = '\0'; - net.n_name = p; - cp = any(p, " \t"); - if (cp == NULL) - goto again; - *cp++ = '\0'; - while (*cp == ' ' || *cp == '\t') - cp++; - p = any(cp, " \t"); - if (p != NULL) - *p++ = '\0'; - net.n_net = inet_network(cp); - net.n_addrtype = AF_INET; - q = net.n_aliases = net_aliases; - if (p != NULL) - cp = p; - while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; - } - if (q < &net_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = any(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - } - *q = NULL; - rv = &net; -DONE: - __UCLIBC_MUTEX_UNLOCK(mylock); - return rv; -} -libc_hidden_def(getnetent) diff --git a/libc/inet/getproto.c b/libc/inet/getproto.c index a079f6487..c59da7e66 100644 --- a/libc/inet/getproto.c +++ b/libc/inet/getproto.c @@ -1,279 +1,182 @@ +/* vi: set sw=4 ts=4: */ /* -** protocols.c /etc/protocols access functions -** -** This file is part of the NYS Library. -** -** The NYS Library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Library General Public License as -** published by the Free Software Foundation; either version 2 of the -** License, or (at your option) any later version. -** -** The NYS Library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Library General Public License for more details. -** -** You should have received a copy of the GNU Library General Public -** License along with the NYS Library; see the file COPYING.LIB. If -** not, write to the Free Software Foundation, Inc., 675 Mass Ave, -** Cambridge, MA 02139, USA. -** -** -** Copyright (c) 1983 Regents of the University of California. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. All advertising materials mentioning features or use of this software -** must display the following acknowledgement: -** This product includes software developed by the University of -** California, Berkeley and its contributors. -** 4. Neither the name of the University nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -** ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -** SUCH DAMAGE. + * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org> + * + * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +/* /etc/protocols +# protocol-name number [aliases ...] +ip 0 IP # internet protocol, pseudo protocol number + +protocol-name: case sensitive friendly name of the IP protocol +number: decimal protocol number +aliases: case sensitive optional space or tab separated list of other names */ -#define __FORCE_GLIBC #include <features.h> -#include <sys/types.h> -#include <sys/socket.h> #include <netdb.h> -#include <stdio.h> -#include <stdlib.h> #include <string.h> +#include <stdlib.h> +#include <netinet/in.h> +#include <arpa/inet.h> #include <errno.h> #include <unistd.h> - -libc_hidden_proto(fopen) -/* Experimentally off - libc_hidden_proto(strcmp) */ -/* Experimentally off - libc_hidden_proto(strpbrk) */ -libc_hidden_proto(atoi) -libc_hidden_proto(rewind) -libc_hidden_proto(fgets) -libc_hidden_proto(fclose) -libc_hidden_proto(abort) +#include "internal/parse_config.h" #include <bits/uClibc_mutex.h> __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); +#define MINTOKENS 2 +#define MAXALIASES 8 /* will probably never be more than one */ +#define MAXTOKENS (MINTOKENS + MAXALIASES + 1) +#define BUFSZ (255) /* one line */ +#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS)) - -#define MAXALIASES 35 -#define SBUFSIZE (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES)) - -static FILE *protof = NULL; -static struct protoent proto; -static char *static_aliases = NULL; +static parser_t *protop = NULL; +static struct protoent protoe; +static char *protobuf = NULL; static smallint proto_stayopen; -static void __initbuf(void) +void setprotoent(int stayopen) { - if (!static_aliases) { - static_aliases = malloc(SBUFSIZE); - if (!static_aliases) - abort(); - } -} - -libc_hidden_proto(setprotoent) -void setprotoent(int f) -{ - __UCLIBC_MUTEX_LOCK(mylock); - if (protof == NULL) - protof = fopen(_PATH_PROTOCOLS, "r" ); - else - rewind(protof); - if (f) proto_stayopen = 1; - __UCLIBC_MUTEX_UNLOCK(mylock); + __UCLIBC_MUTEX_LOCK(mylock); + if (protop) + config_close(protop); + protop = config_open(_PATH_PROTOCOLS); + if (stayopen) + proto_stayopen = 1; + __UCLIBC_MUTEX_UNLOCK(mylock); } libc_hidden_def(setprotoent) -libc_hidden_proto(endprotoent) void endprotoent(void) { - __UCLIBC_MUTEX_LOCK(mylock); - if (protof) { - fclose(protof); - protof = NULL; - } - proto_stayopen = 0; - __UCLIBC_MUTEX_UNLOCK(mylock); + __UCLIBC_MUTEX_LOCK(mylock); + if (protop) { + config_close(protop); + protop = NULL; + } + proto_stayopen = 0; + __UCLIBC_MUTEX_UNLOCK(mylock); } libc_hidden_def(endprotoent) -libc_hidden_proto(getprotoent_r) int getprotoent_r(struct protoent *result_buf, - char *buf, size_t buflen, - struct protoent **result) + char *buf, size_t buflen, struct protoent **result) { - char *p; - register char *cp, **q; - char **proto_aliases; - char *line; - int rv; - - *result = NULL; - - if (buflen < sizeof(*proto_aliases)*MAXALIASES) { - errno=ERANGE; + char **tok = NULL; + const size_t aliaslen = sizeof(char *) * MAXTOKENS; + int ret = ERANGE; + + *result = NULL; + if (buflen < aliaslen + || (buflen - aliaslen) < BUFSZ + 1) + goto DONE_NOUNLOCK; + + __UCLIBC_MUTEX_LOCK(mylock); + //tok = (char **) buf; + ret = ENOENT; + if (protop == NULL) + setprotoent(proto_stayopen); + if (protop == NULL) + goto DONE; + protop->data = buf; + protop->data_len = aliaslen; + protop->line_len = buflen - aliaslen; + /* <name>[[:space:]]<protonumber>[[:space:]][<aliases>] */ + if (!config_read(protop, &tok, MAXTOKENS - 1, MINTOKENS, "# \t/", PARSE_NORMAL)) { + goto DONE; + } + result_buf->p_name = *(tok++); + result_buf->p_proto = atoi(*(tok++)); + result_buf->p_aliases = tok; + *result = result_buf; + ret = 0; + DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + DONE_NOUNLOCK: + errno = ret; return errno; - } - __UCLIBC_MUTEX_LOCK(mylock); - proto_aliases=(char **)buf; - buf+=sizeof(*proto_aliases)*MAXALIASES; - buflen-=sizeof(*proto_aliases)*MAXALIASES; - - if (buflen < BUFSIZ+1) { - errno=rv=ERANGE; - goto DONE; - } - line=buf; - buf+=BUFSIZ+1; - buflen-=BUFSIZ+1; - - if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL) { - rv=errno; - goto DONE; - } -again: - if ((p = fgets(line, BUFSIZ, protof)) == NULL) { - rv=TRY_AGAIN; - goto DONE; - } +} +libc_hidden_def(getprotoent_r) - if (*p == '#') - goto again; - cp = strpbrk(p, "#\n"); - if (cp == NULL) - goto again; - *cp = '\0'; - result_buf->p_name = p; - cp = strpbrk(p, " \t"); - if (cp == NULL) - goto again; - *cp++ = '\0'; - while (*cp == ' ' || *cp == '\t') - cp++; - p = strpbrk(cp, " \t"); - if (p != NULL) - *p++ = '\0'; - result_buf->p_proto = atoi(cp); - q = result_buf->p_aliases = proto_aliases; - if (p != NULL) { - cp = p; - while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; - } - if (q < &proto_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; +static void __initbuf(void) +{ + if (!protobuf) { + protobuf = malloc(SBUFSIZE); + if (!protobuf) + abort(); } - } - *q = NULL; - *result=result_buf; - rv = 0; -DONE: - __UCLIBC_MUTEX_UNLOCK(mylock); - return rv; } -libc_hidden_def(getprotoent_r) -struct protoent * getprotoent(void) +struct protoent *getprotoent(void) { - struct protoent *result; + struct protoent *result; - __initbuf(); - getprotoent_r(&proto, static_aliases, SBUFSIZE, &result); - return result; + __initbuf(); + getprotoent_r(&protoe, protobuf, SBUFSIZE, &result); + return result; } - -libc_hidden_proto(getprotobyname_r) int getprotobyname_r(const char *name, - struct protoent *result_buf, - char *buf, size_t buflen, - struct protoent **result) + struct protoent *result_buf, char *buf, size_t buflen, + struct protoent **result) { - register char **cp; - int ret; - - __UCLIBC_MUTEX_LOCK(mylock); - setprotoent(proto_stayopen); - while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) { - if (strcmp(result_buf->p_name, name) == 0) - break; - for (cp = result_buf->p_aliases; *cp != 0; cp++) - if (strcmp(*cp, name) == 0) - goto found; - } -found: - if (!proto_stayopen) - endprotoent(); - __UCLIBC_MUTEX_UNLOCK(mylock); - return *result?0:ret; + register char **cp; + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + setprotoent(proto_stayopen); + while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) { + if (strcmp(name, result_buf->p_name) == 0) + break; + for (cp = result_buf->p_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + } + gotname: + if (!proto_stayopen) + endprotoent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; } libc_hidden_def(getprotobyname_r) - -struct protoent * getprotobyname(const char *name) +struct protoent *getprotobyname(const char *name) { - struct protoent *result; + struct protoent *result; - __initbuf(); - getprotobyname_r(name, &proto, static_aliases, SBUFSIZE, &result); - return result; + __initbuf(); + getprotobyname_r(name, &protoe, protobuf, SBUFSIZE, &result); + return result; } - -libc_hidden_proto(getprotobynumber_r) -int getprotobynumber_r (int proto_num, - struct protoent *result_buf, - char *buf, size_t buflen, - struct protoent **result) +int getprotobynumber_r(int proto, + struct protoent *result_buf, char *buf, + size_t buflen, struct protoent **result) { - int ret; + int ret; - __UCLIBC_MUTEX_LOCK(mylock); - setprotoent(proto_stayopen); - while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) - if (result_buf->p_proto == proto_num) - break; - if (!proto_stayopen) - endprotoent(); - __UCLIBC_MUTEX_UNLOCK(mylock); - return *result?0:ret; + __UCLIBC_MUTEX_LOCK(mylock); + setprotoent(proto_stayopen); + while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) { + if (proto == result_buf->p_proto) + break; + } + if (!proto_stayopen) + endprotoent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; } libc_hidden_def(getprotobynumber_r) -struct protoent * getprotobynumber(int proto_num) +struct protoent *getprotobynumber(int proto) { - struct protoent *result; + struct protoent *result; - __initbuf(); - getprotobynumber_r(proto_num, &proto, static_aliases, - SBUFSIZE, &result); - return result; + __initbuf(); + getprotobynumber_r(proto, &protoe, protobuf, SBUFSIZE, &result); + return result; } diff --git a/libc/inet/getservice.c b/libc/inet/getservice.c index bb1d6d2e4..183099f5c 100644 --- a/libc/inet/getservice.c +++ b/libc/inet/getservice.c @@ -1,285 +1,190 @@ +/* vi: set sw=4 ts=4: */ /* -** services.c /etc/services access functions -** -** This file is part of the NYS Library. -** -** The NYS Library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Library General Public License as -** published by the Free Software Foundation; either version 2 of the -** License, or (at your option) any later version. -** -** The NYS Library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Library General Public License for more details. -** -** You should have received a copy of the GNU Library General Public -** License along with the NYS Library; see the file COPYING.LIB. If -** not, write to the Free Software Foundation, Inc., 675 Mass Ave, -** Cambridge, MA 02139, USA. -** -** -** Copyright (c) 1983 Regents of the University of California. -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. All advertising materials mentioning features or use of this software -** must display the following acknowledgement: -** This product includes software developed by the University of -** California, Berkeley and its contributors. -** 4. Neither the name of the University nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -** ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -** SUCH DAMAGE. + * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org> + * + * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +/* /etc/services +# service-name port/protocol [aliases ...] +discard 9/udp sink null + +service-name: case sensitive friendly name of the service +port: decimal port number +protocol: protocols(5) compatible entry +aliases: case sensitive optional space or tab separated list of other names */ -#define __FORCE_GLIBC #include <features.h> -#include <sys/types.h> -#include <sys/socket.h> #include <netdb.h> -#include <stdio.h> #include <string.h> #include <stdlib.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <unistd.h> - -/* Experimentally off - libc_hidden_proto(strcmp) */ -/* Experimentally off - libc_hidden_proto(strpbrk) */ -libc_hidden_proto(fopen) -libc_hidden_proto(fclose) -libc_hidden_proto(atoi) -libc_hidden_proto(rewind) -libc_hidden_proto(fgets) -libc_hidden_proto(abort) +#include "internal/parse_config.h" #include <bits/uClibc_mutex.h> __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); +#define MINTOKENS 3 +#define MAXALIASES 8 /* we seldomly need more than 1 alias */ +#define MAXTOKENS (MINTOKENS + MAXALIASES + 1) +#define BUFSZ (255) /* one line */ +#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS)) - - -#define MAXALIASES 35 -#define SBUFSIZE (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES)) - -static FILE *servf = NULL; -static struct servent serv; +static parser_t *servp = NULL; +static struct servent serve; static char *servbuf = NULL; +static size_t servbuf_sz = SBUFSIZE; static smallint serv_stayopen; -static void __initbuf(void) +void setservent(int stayopen) { - if (!servbuf) { - servbuf = malloc(SBUFSIZE); - if (!servbuf) - abort(); - } -} - -libc_hidden_proto(setservent) -void setservent(int f) -{ - __UCLIBC_MUTEX_LOCK(mylock); - if (servf == NULL) - servf = fopen(_PATH_SERVICES, "r" ); - else - rewind(servf); - if (f) serv_stayopen = 1; - __UCLIBC_MUTEX_UNLOCK(mylock); + __UCLIBC_MUTEX_LOCK(mylock); + if (servp) + config_close(servp); + servp = config_open(_PATH_SERVICES); + if (stayopen) + serv_stayopen = 1; + __UCLIBC_MUTEX_UNLOCK(mylock); } libc_hidden_def(setservent) -libc_hidden_proto(endservent) void endservent(void) { - __UCLIBC_MUTEX_LOCK(mylock); - if (servf) { - fclose(servf); - servf = NULL; - } - serv_stayopen = 0; - __UCLIBC_MUTEX_UNLOCK(mylock); + __UCLIBC_MUTEX_LOCK(mylock); + if (servp) { + config_close(servp); + servp = NULL; + } + serv_stayopen = 0; + __UCLIBC_MUTEX_UNLOCK(mylock); } libc_hidden_def(endservent) -libc_hidden_proto(getservent_r) -int getservent_r(struct servent * result_buf, - char * buf, size_t buflen, - struct servent ** result) +int getservent_r(struct servent *result_buf, + char *buf, size_t buflen, struct servent **result) { - char *p; - register char *cp, **q; - char **serv_aliases; - char *line; - int rv; - - *result=NULL; - - if (buflen < sizeof(*serv_aliases)*MAXALIASES) { - errno=ERANGE; - return errno; - } - __UCLIBC_MUTEX_LOCK(mylock); - serv_aliases=(char **)buf; - buf+=sizeof(*serv_aliases)*MAXALIASES; - buflen-=sizeof(*serv_aliases)*MAXALIASES; - - if (buflen < BUFSIZ+1) { - errno=rv=ERANGE; - goto DONE; - } - line=buf; - buf+=BUFSIZ+1; - buflen-=BUFSIZ+1; - - if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) { - errno=rv=EIO; - goto DONE; - } -again: - if ((p = fgets(line, BUFSIZ, servf)) == NULL) { - errno=rv=EIO; - goto DONE; - } - if (*p == '#') - goto again; - cp = strpbrk(p, "#\n"); - if (cp == NULL) - goto again; - *cp = '\0'; - result_buf->s_name = p; - p = strpbrk(p, " \t"); - if (p == NULL) - goto again; - *p++ = '\0'; - while (*p == ' ' || *p == '\t') - p++; - cp = strpbrk(p, ",/"); - if (cp == NULL) - goto again; - *cp++ = '\0'; - result_buf->s_port = htons((u_short)atoi(p)); - result_buf->s_proto = cp; - q = result_buf->s_aliases = serv_aliases; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; + char **tok = NULL; + const size_t aliaslen = sizeof(char *) * MAXTOKENS; + int ret = ERANGE; + + *result = NULL; + if (buflen < aliaslen + || (buflen - aliaslen) < BUFSZ + 1) + goto DONE_NOUNLOCK; + + __UCLIBC_MUTEX_LOCK(mylock); + ret = ENOENT; + if (servp == NULL) + setservent(serv_stayopen); + if (servp == NULL) + goto DONE; + + servp->data = buf; + servp->data_len = aliaslen; + servp->line_len = buflen - aliaslen; + /* <name>[[:space:]]<port>/<proto>[[:space:]][<aliases>] */ + if (!config_read(servp, &tok, MAXTOKENS - 1, MINTOKENS, "# \t/", PARSE_NORMAL)) { + goto DONE; } - if (q < &serv_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - } - *q = NULL; - *result=result_buf; - rv = 0; -DONE: - __UCLIBC_MUTEX_UNLOCK(mylock); - return rv; + result_buf->s_name = *(tok++); + result_buf->s_port = htons((u_short) atoi(*(tok++))); + result_buf->s_proto = *(tok++); + result_buf->s_aliases = tok; + *result = result_buf; + ret = 0; + DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + DONE_NOUNLOCK: + errno = ret; + return errno; } libc_hidden_def(getservent_r) -struct servent * getservent(void) +static void __initbuf(void) { - struct servent *result; + if (!servbuf) + servbuf = malloc(SBUFSIZE); + if (!servbuf) + abort(); +} - __initbuf(); - getservent_r(&serv, servbuf, SBUFSIZE, &result); - return result; +struct servent *getservent(void) +{ + struct servent *result; + + __initbuf(); + getservent_r(&serve, servbuf, servbuf_sz, &result); + return result; } -libc_hidden_proto(getservbyname_r) int getservbyname_r(const char *name, const char *proto, - struct servent * result_buf, char * buf, size_t buflen, - struct servent ** result) + struct servent *result_buf, char *buf, size_t buflen, + struct servent **result) { - register char **cp; - int ret; - - __UCLIBC_MUTEX_LOCK(mylock); - setservent(serv_stayopen); - while (!(ret=getservent_r(result_buf, buf, buflen, result))) { - if (strcmp(name, result_buf->s_name) == 0) - goto gotname; - for (cp = result_buf->s_aliases; *cp; cp++) - if (strcmp(name, *cp) == 0) - goto gotname; - continue; -gotname: - if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) - break; - } - if (!serv_stayopen) - endservent(); - __UCLIBC_MUTEX_UNLOCK(mylock); - return *result?0:ret; + register char **cp; + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + setservent(serv_stayopen); + while (!(ret = getservent_r(result_buf, buf, buflen, result))) { + if (strcmp(name, result_buf->s_name) == 0) + goto gotname; + for (cp = result_buf->s_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + continue; + gotname: + if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) + break; + } + if (!serv_stayopen) + endservent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; } libc_hidden_def(getservbyname_r) struct servent *getservbyname(const char *name, const char *proto) { - struct servent *result; + struct servent *result; - __initbuf(); - getservbyname_r(name, proto, &serv, servbuf, SBUFSIZE, &result); - return result; + __initbuf(); + getservbyname_r(name, proto, &serve, servbuf, servbuf_sz, &result); + return result; } -libc_hidden_proto(getservbyport_r) int getservbyport_r(int port, const char *proto, - struct servent * result_buf, char * buf, - size_t buflen, struct servent ** result) + struct servent *result_buf, char *buf, + size_t buflen, struct servent **result) { - int ret; - - __UCLIBC_MUTEX_LOCK(mylock); - setservent(serv_stayopen); - while (!(ret=getservent_r(result_buf, buf, buflen, result))) { - if (result_buf->s_port != port) - continue; - if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) - break; - } - if (!serv_stayopen) - endservent(); - __UCLIBC_MUTEX_UNLOCK(mylock); - return *result?0:ret; + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + setservent(serv_stayopen); + while (!(ret = getservent_r(result_buf, buf, buflen, result))) { + if (result_buf->s_port != port) + continue; + if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) + break; + } + if (!serv_stayopen) + endservent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; } libc_hidden_def(getservbyport_r) -libc_hidden_proto(getservbyport) -struct servent * getservbyport(int port, const char *proto) +struct servent *getservbyport(int port, const char *proto) { - struct servent *result; + struct servent *result; - __initbuf(); - getservbyport_r(port, proto, &serv, servbuf, SBUFSIZE, &result); - return result; + __initbuf(); + getservbyport_r(port, proto, &serve, servbuf, servbuf_sz, &result); + return result; } libc_hidden_def(getservbyport) diff --git a/libc/inet/herror.c b/libc/inet/herror.c index 063f6e93e..53d29ff3d 100644 --- a/libc/inet/herror.c +++ b/libc/inet/herror.c @@ -17,16 +17,12 @@ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define __FORCE_GLIBC -#include <features.h> #include <stdio.h> #include <string.h> #include <netdb.h> -libc_hidden_proto(fprintf) -libc_hidden_proto(__h_errno_location) -static const char *error_msg = "Resolver error"; +static const char error_msg[] = "Resolver error"; static const char *const h_errlist[] = { "Error 0", "Unknown host", /* 1 HOST_NOT_FOUND */ @@ -39,7 +35,6 @@ static const int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; /* * herror -- print the error indicated by the h_errno value. */ -libc_hidden_proto(herror) void herror(const char *s) { static const char colon_space[] = ": "; @@ -52,7 +47,7 @@ void herror(const char *s) } p = error_msg; if ((h_errno >= 0) && (h_errno < h_nerr)) { - p = h_errlist[h_errno]; + p = h_errlist[h_errno]; } fprintf(stderr, "%s%s%s\n", s, c, p); } @@ -61,10 +56,8 @@ libc_hidden_def(herror) const char *hstrerror(int err) { - if (err < 0) { - return(error_msg); - } else if (err < h_nerr) { - return(h_errlist[err]); - } - return(error_msg); + if ((unsigned)err < h_nerr) + return(h_errlist[err]); + + return error_msg; } diff --git a/libc/inet/hostid.c b/libc/inet/hostid.c index 4972dcec2..d05a84f68 100644 --- a/libc/inet/hostid.c +++ b/libc/inet/hostid.c @@ -1,29 +1,18 @@ +/* vi: set sw=4 ts=4: */ /* * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> * * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ -#define __FORCE_GLIBC -#include <features.h> -#include <stdio.h> -#include <string.h> #include <errno.h> -#include <sys/param.h> -#include <netinet/in.h> -#include <netdb.h> -#include <fcntl.h> #include <unistd.h> - -/* Experimentally off - libc_hidden_proto(memcpy) */ -libc_hidden_proto(open) -libc_hidden_proto(close) -libc_hidden_proto(read) -libc_hidden_proto(write) -libc_hidden_proto(getuid) -libc_hidden_proto(geteuid) -libc_hidden_proto(gethostbyname_r) -libc_hidden_proto(gethostname) +#include <sys/types.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <netdb.h> +#include <not-cancel.h> #define HOSTID "/etc/hostid" @@ -33,31 +22,34 @@ int sethostid(long int new_id) int fd; int ret; - if (geteuid() || getuid()) return __set_errno(EPERM); - if ((fd=open(HOSTID,O_CREAT|O_WRONLY,0644))<0) return -1; - ret = write(fd,(void *)&new_id,sizeof(new_id)) == sizeof(new_id) - ? 0 : -1; - close (fd); + if (geteuid() || getuid()) + return __set_errno(EPERM); + fd = open_not_cancel(HOSTID, O_CREAT|O_WRONLY, 0644); + if (fd < 0) + return fd; + ret = write_not_cancel(fd, &new_id, sizeof(new_id)) == sizeof(new_id) ? 0 : -1; + close_not_cancel_no_status (fd); return ret; } #endif +#define _addr(a) (((struct sockaddr_in*)a->ai_addr)->sin_addr.s_addr) long int gethostid(void) { - char host[MAXHOSTNAMELEN + 1]; - int fd, id; + char host[HOST_NAME_MAX + 1]; + int fd, id = 0; /* If hostid was already set then we can return that value. * It is not an error if we cannot read this file. It is not even an * error if we cannot read all the bytes, we just carry on trying... */ - if ((fd=open(HOSTID,O_RDONLY))>=0 && read(fd,(void *)&id,sizeof(id))) - { - close (fd); - return id; + fd = open_not_cancel_2(HOSTID, O_RDONLY); + if (fd >= 0) { + int i = read_not_cancel(fd, &id, sizeof(id)); + close_not_cancel_no_status(fd); + if (i > 0) + return id; } - if (fd >= 0) close (fd); - /* Try some methods of returning a unique 32 bit id. Clearly IP * numbers, if on the internet, will have a unique address. If they * are not on the internet then we can return 0 which means they should @@ -69,36 +61,18 @@ long int gethostid(void) * setting one anyway. * Mitch */ - if (gethostname(host,MAXHOSTNAMELEN)>=0 && *host) { - struct hostent *hp; - struct in_addr in; - struct hostent ghbn_h; - char ghbn_buf[sizeof(struct in_addr) + - sizeof(struct in_addr *)*2 + - sizeof(char *)*((2 + 5/*MAX_ALIASES*/ + - 1)/*ALIAS_DIM*/) + - 256/*namebuffer*/ + 32/* margin */]; - int ghbn_errno; - - /* replace gethostbyname() with gethostbyname_r() - ron@zing.net */ - /*if ((hp = gethostbyname(host)) == (struct hostent *)NULL)*/ - gethostbyname_r(host, &ghbn_h, ghbn_buf, sizeof(ghbn_buf), &hp, &ghbn_errno); - - if (hp == (struct hostent *)NULL) - - /* This is not a error if we get here, as all it means is that - * this host is not on a network and/or they have not - * configured their network properly. So we return the unset - * hostid which should be 0, meaning that they should set it !! - */ - return 0; - else { - memcpy((char *) &in, (char *) hp->h_addr, hp->h_length); - - /* Just so it doesn't look exactly like the IP addr */ - return(in.s_addr<<16|in.s_addr>>16); + if (gethostname(host, HOST_NAME_MAX) >= 0 && *host) { + struct addrinfo hints, *results, *addr; + memset(&hints, 0, sizeof(struct addrinfo)); + if (!getaddrinfo(host, NULL, &hints, &results)) { + for (addr = results; addr; addr = results->ai_next) { + /* Just so it doesn't look exactly like the + IP addr */ + id = _addr(addr) << 16 | _addr(addr) >> 16; + break; + } + freeaddrinfo(results); } } - else return 0; - + return id; } diff --git a/libc/inet/if_index.c b/libc/inet/if_index.c index 36c6be45c..2d7ab27fa 100644 --- a/libc/inet/if_index.c +++ b/libc/inet/if_index.c @@ -13,15 +13,12 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. + License along with the GNU C Library; see the file COPYING.LIB. If + not, see <http://www.gnu.org/licenses/>. Reworked Dec 2002 by Erik Andersen <andersen@codepoet.org> */ -#define __FORCE_GLIBC -#include <features.h> #include <string.h> #include <alloca.h> #include <errno.h> @@ -31,21 +28,12 @@ #include <net/if.h> #include <sys/socket.h> #include <sys/ioctl.h> -#include <libc-internal.h> +#include <not-cancel.h> #include "netlinkaccess.h" -/* Experimentally off - libc_hidden_proto(strncpy) */ -/* Experimentally off - libc_hidden_proto(strdup) */ -libc_hidden_proto(ioctl) -libc_hidden_proto(close) -#if __ASSUME_NETLINK_SUPPORT -/* Experimentally off - libc_hidden_proto(strndup) */ -#endif - extern int __opensock(void) attribute_hidden; -libc_hidden_proto(if_nametoindex) unsigned int if_nametoindex(const char* ifname) { @@ -62,20 +50,20 @@ if_nametoindex(const char* ifname) strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl (fd, SIOCGIFINDEX, &ifr) < 0) { - int saved_errno = errno; - close(fd); - if (saved_errno == EINVAL) - __set_errno(ENOSYS); + /* close never fails here, fd is just a unconnected socket. + *int saved_errno = errno; */ + close_not_cancel_no_status(fd); + /*if (saved_errno == EINVAL) + * __set_errno(ENOSYS); */ return 0; } - close(fd); + close_not_cancel_no_status(fd); return ifr.ifr_ifindex; #endif } libc_hidden_def(if_nametoindex) -libc_hidden_proto(if_freenameindex) void if_freenameindex (struct if_nameindex *ifn) { @@ -89,7 +77,6 @@ if_freenameindex (struct if_nameindex *ifn) } libc_hidden_def(if_freenameindex) -libc_hidden_proto(if_nameindex) #if !__ASSUME_NETLINK_SUPPORT struct if_nameindex * if_nameindex (void) @@ -122,7 +109,7 @@ if_nameindex (void) if (ioctl (fd, SIOCGIFCONF, &ifc) < 0) { - close (fd); + close_not_cancel_no_status (fd); return NULL; } } @@ -133,7 +120,7 @@ if_nameindex (void) idx = malloc ((nifs + 1) * sizeof (struct if_nameindex)); if (idx == NULL) { - close(fd); + close_not_cancel_no_status (fd); __set_errno(ENOBUFS); return NULL; } @@ -151,7 +138,7 @@ if_nameindex (void) for (j = 0; j < i; ++j) free (idx[j].if_name); free(idx); - close(fd); + close_not_cancel_no_status (fd); if (saved_errno == EINVAL) saved_errno = ENOSYS; else if (saved_errno == ENOMEM) @@ -165,7 +152,7 @@ if_nameindex (void) idx[i].if_index = 0; idx[i].if_name = NULL; - close(fd); + close_not_cancel_no_status (fd); return idx; #endif } @@ -308,14 +295,14 @@ if_indextoname (unsigned int ifindex, char *ifname) if (ioctl (fd, SIOCGIFNAME, &ifr) < 0) { int serrno = errno; - close (fd); + close_not_cancel_no_status (fd); if (serrno == ENODEV) /* POSIX requires ENXIO. */ serrno = ENXIO; __set_errno (serrno); return NULL; } - close (fd); + close_not_cancel_no_status (fd); return strncpy (ifname, ifr.ifr_name, IFNAMSIZ); # else diff --git a/libc/inet/ifaddrs.c b/libc/inet/ifaddrs.c index c60dcf76d..0c9310651 100644 --- a/libc/inet/ifaddrs.c +++ b/libc/inet/ifaddrs.c @@ -13,12 +13,9 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ -#define __FORCE_GLIBC -#include <features.h> #include <alloca.h> #include <assert.h> #include <errno.h> @@ -33,23 +30,11 @@ #include <string.h> #include <sys/ioctl.h> #include <sys/socket.h> -#include <libc-internal.h> #include <time.h> #include <unistd.h> #include "netlinkaccess.h" -libc_hidden_proto(socket) -libc_hidden_proto(close) -/* Experimentally off - libc_hidden_proto(time) */ -libc_hidden_proto(sendto) -libc_hidden_proto(recvmsg) -libc_hidden_proto(bind) -/* Experimentally off - libc_hidden_proto(memset) */ -/* Experimentally off - libc_hidden_proto(mempcpy) */ -libc_hidden_proto(getsockname) -libc_hidden_proto(fclose) -libc_hidden_proto(abort) #ifndef __libc_use_alloca # define __libc_use_alloca(x) (x < __MAX_ALLOCA_CUTOFF) @@ -70,7 +55,9 @@ struct ifaddrs_storage struct sockaddr sa; struct sockaddr_ll sl; struct sockaddr_in s4; +#ifdef __UCLIBC_HAS_IPV6__ struct sockaddr_in6 s6; +#endif } addr, netmask, broadaddr; char name[IF_NAMESIZE + 1]; }; @@ -81,7 +68,6 @@ void __netlink_free_handle (struct netlink_handle *h) { struct netlink_res *ptr; - int saved_errno = errno; ptr = h->nlm_list; while (ptr != NULL) @@ -89,11 +75,9 @@ __netlink_free_handle (struct netlink_handle *h) struct netlink_res *tmpptr; tmpptr = ptr->next; - free (ptr); + free (ptr); /* doesn't affect errno */ ptr = tmpptr; } - - __set_errno (saved_errno); } @@ -131,7 +115,8 @@ __netlink_request (struct netlink_handle *h, int type) { struct netlink_res *nlm_next; struct netlink_res **new_nlm_list; - static volatile size_t buf_size = 4096; + static volatile size_t buf_size = 0; + size_t this_buf_size; char *buf; struct sockaddr_nl nladdr; struct nlmsghdr *nlmh; @@ -142,7 +127,15 @@ __netlink_request (struct netlink_handle *h, int type) if (__netlink_sendreq (h, type) < 0) return -1; - size_t this_buf_size = buf_size; + if (buf_size) + this_buf_size = buf_size; + else { +#ifdef PAGE_SIZE + this_buf_size = PAGE_SIZE; +#else + this_buf_size = __pagesize; +#endif + } if (__libc_use_alloca (this_buf_size)) buf = alloca (this_buf_size); else @@ -308,9 +301,6 @@ __netlink_open (struct netlink_handle *h) close_and_out: __netlink_close (h); out: -#if __ASSUME_NETLINK_SUPPORT == 0 - __no_netlink_support = 1; -#endif return -1; } /* Determine the ID the kernel assigned for this netlink connection. @@ -333,7 +323,7 @@ __netlink_open (struct netlink_handle *h) that a RTM_NEWADDR index is not known to this map. */ static int internal_function -map_newlink (int index, struct ifaddrs_storage *ifas, int *map, int max) +map_newlink (int idx, struct ifaddrs_storage *ifas, int *map, int max) { int i; @@ -341,12 +331,12 @@ map_newlink (int index, struct ifaddrs_storage *ifas, int *map, int max) { if (map[i] == -1) { - map[i] = index; + map[i] = idx; if (i > 0) ifas[i - 1].ifa.ifa_next = &ifas[i].ifa; return i; } - else if (map[i] == index) + else if (map[i] == idx) return i; } /* This should never be reached. If this will be reached, we have @@ -374,18 +364,11 @@ getifaddrs (struct ifaddrs **ifap) if (ifap) *ifap = NULL; - if (! __no_netlink_support && __netlink_open (&nh) < 0) + if (__netlink_open (&nh) < 0) { -#if __ASSUME_NETLINK_SUPPORT != 0 return -1; -#endif } -#if __ASSUME_NETLINK_SUPPORT == 0 - if (__no_netlink_support) - return fallback_getifaddrs (ifap); -#endif - /* Tell the kernel that we wish to get a list of all active interfaces, collect all data for every interface. */ if (__netlink_request (&nh, RTM_GETLINK) < 0) @@ -462,10 +445,7 @@ getifaddrs (struct ifaddrs **ifap) /* Allocate memory for all entries we have and initialize next pointer. */ - ifas = (struct ifaddrs_storage *) calloc (1, - (newlink + newaddr) - * sizeof (struct ifaddrs_storage) - + ifa_data_size); + ifas = calloc (1, (newlink + newaddr) * sizeof (ifas[0]) + ifa_data_size); if (ifas == NULL) { result = -1; @@ -648,6 +628,7 @@ getifaddrs (struct ifaddrs **ifap) rta_data, rta_payload); break; +#ifdef __UCLIBC_HAS_IPV6__ case AF_INET6: /* Size must match that of an address for IPv6. */ if (rta_payload == 16) @@ -660,6 +641,7 @@ getifaddrs (struct ifaddrs **ifap) = ifam->ifa_index; } break; +#endif default: if (rta_payload <= sizeof (ifas[ifa_index].addr)) @@ -695,6 +677,7 @@ getifaddrs (struct ifaddrs **ifap) rta_data, rta_payload); break; +#ifdef __UCLIBC_HAS_IPV6__ case AF_INET6: /* Size must match that of an address for IPv6. */ if (rta_payload == 16) @@ -707,6 +690,7 @@ getifaddrs (struct ifaddrs **ifap) ifam->ifa_index; } break; +#endif default: if (rta_payload <= sizeof (ifas[ifa_index].addr)) @@ -736,6 +720,7 @@ getifaddrs (struct ifaddrs **ifap) rta_data, rta_payload); break; +#ifdef __UCLIBC_HAS_IPV6__ case AF_INET6: /* Size must match that of an address for IPv6. */ if (rta_payload == 16) @@ -748,6 +733,7 @@ getifaddrs (struct ifaddrs **ifap) = ifam->ifa_index; } break; +#endif default: if (rta_payload <= sizeof (ifas[ifa_index].addr)) @@ -804,10 +790,12 @@ getifaddrs (struct ifaddrs **ifap) max_prefixlen = 32; break; +#ifdef __UCLIBC_HAS_IPV6__ case AF_INET6: cp = (char *) &ifas[ifa_index].netmask.s6.sin6_addr; max_prefixlen = 128; break; +#endif } ifas[ifa_index].ifa.ifa_netmask->sa_family @@ -862,15 +850,14 @@ getifaddrs (struct ifaddrs **ifap) return result; } +libc_hidden_def(getifaddrs) - -#if __ASSUME_NETLINK_SUPPORT != 0 void freeifaddrs (struct ifaddrs *ifa) { free (ifa); } -#endif +libc_hidden_def(freeifaddrs) #endif /* __UCLIBC_SUPPORT_AI_ADDRCONFIG__ */ diff --git a/libc/inet/in6_addr.c b/libc/inet/in6_addr.c index c2ab375e6..2d0d0182f 100644 --- a/libc/inet/in6_addr.c +++ b/libc/inet/in6_addr.c @@ -13,18 +13,14 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ -#define __FORCE_GLIBC -#include <features.h> #include <netinet/in.h> #ifdef __UCLIBC_HAS_IPV6__ const struct in6_addr in6addr_any = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }; -libc_hidden_proto(in6addr_loopback) const struct in6_addr in6addr_loopback = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }; libc_hidden_data_def(in6addr_loopback) diff --git a/libc/inet/inet_addr.c b/libc/inet/inet_addr.c index 445f850a1..9f946967c 100644 --- a/libc/inet/inet_addr.c +++ b/libc/inet/inet_addr.c @@ -4,5 +4,5 @@ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ -#define L_inet_makeaddr +#define L_inet_addr #include "addr.c" diff --git a/libc/inet/inet_makeaddr.c b/libc/inet/inet_makeaddr.c index 9f946967c..445f850a1 100644 --- a/libc/inet/inet_makeaddr.c +++ b/libc/inet/inet_makeaddr.c @@ -4,5 +4,5 @@ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ -#define L_inet_addr +#define L_inet_makeaddr #include "addr.c" diff --git a/libc/inet/inet_net.c b/libc/inet/inet_net.c index e46c9a561..a1d2b3d85 100644 --- a/libc/inet/inet_net.c +++ b/libc/inet/inet_net.c @@ -32,24 +32,15 @@ * SUCH DAMAGE. */ -#define __FORCE_GLIBC -#include <features.h> #include <ctype.h> #include <netinet/in.h> #include <arpa/inet.h> -#ifdef __UCLIBC_HAS_XLOCALE__ -libc_hidden_proto(__ctype_b_loc) -#elif defined __UCLIBC_HAS_CTYPE_TABLES__ -libc_hidden_proto(__ctype_b) -#endif - /* * Internet network address interpretation routine. * The library routines call this routine to interpret * network numbers. */ -libc_hidden_proto(inet_network) in_addr_t inet_network(const char *cp) { diff --git a/libc/inet/lengthd.c b/libc/inet/lengthd.c index 07c7fc6f1..d2db685b9 100644 --- a/libc/inet/lengthd.c +++ b/libc/inet/lengthd.c @@ -5,4 +5,4 @@ */ #define L_lengthd -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/lengthq.c b/libc/inet/lengthq.c index e62e6f25a..beeafc1d2 100644 --- a/libc/inet/lengthq.c +++ b/libc/inet/lengthq.c @@ -5,4 +5,4 @@ */ #define L_lengthq -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/netlinkaccess.h b/libc/inet/netlinkaccess.h index acadcb544..e9017cdd4 100644 --- a/libc/inet/netlinkaccess.h +++ b/libc/inet/netlinkaccess.h @@ -12,9 +12,8 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #ifndef _NETLINKACCESS_H #define _NETLINKACCESS_H 1 @@ -22,27 +21,11 @@ #include <features.h> #include <stdint.h> #include <unistd.h> -#include <sys/types.h> - -#define _LINUX_TYPES_H -typedef uint8_t __u8; -typedef uint16_t __u16; -typedef uint32_t __u32; -typedef uint64_t __u64; -typedef int32_t __s32; +#if defined __ASSUME_NETLINK_SUPPORT || defined __UCLIBC_USE_NETLINK__ +#include <asm/types.h> #include <linux/rtnetlink.h> #include <linux/netlink.h> -/* Should prob be a configure option or something */ -#ifndef __ASSUME_NETLINK_SUPPORT -#ifdef __UCLIBC_USE_NETLINK__ -# define __ASSUME_NETLINK_SUPPORT 1 -#else -# define __ASSUME_NETLINK_SUPPORT 0 -#endif -#endif - - struct netlink_res { struct netlink_res *next; @@ -62,19 +45,17 @@ struct netlink_handle }; -#ifdef __UCLIBC_SUPPORT_AI_ADDRCONFIG__ -#if __ASSUME_NETLINK_SUPPORT == 0 -extern smallint __no_netlink_support attribute_hidden; -#else -# define __no_netlink_support 0 +#ifndef __ASSUME_NETLINK_SUPPORT +#define __ASSUME_NETLINK_SUPPORT 1 #endif -#endif /* __UCLIBC_SUPPORT_AI_ADDRCONFIG__ */ - extern int __netlink_open (struct netlink_handle *h) attribute_hidden; extern void __netlink_close (struct netlink_handle *h) attribute_hidden; extern void __netlink_free_handle (struct netlink_handle *h) attribute_hidden; extern int __netlink_request (struct netlink_handle *h, int type) attribute_hidden; +#else +#define __ASSUME_NETLINK_SUPPORT 0 +#endif -#endif /* netlinkaccess.h */ +#endif /* _NETLINKACCESS_H */ diff --git a/libc/inet/ns_name.c b/libc/inet/ns_name.c index 158a1a331..9df9464a3 100644 --- a/libc/inet/ns_name.c +++ b/libc/inet/ns_name.c @@ -5,4 +5,4 @@ */ #define L_ns_name -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/ns_netint.c b/libc/inet/ns_netint.c new file mode 100644 index 000000000..acf88dc68 --- /dev/null +++ b/libc/inet/ns_netint.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_ns_netint +#include RESOLVER diff --git a/libc/inet/ns_parse.c b/libc/inet/ns_parse.c new file mode 100644 index 000000000..e7aecb421 --- /dev/null +++ b/libc/inet/ns_parse.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_ns_parse +#include RESOLVER diff --git a/libc/inet/ntohl.c b/libc/inet/ntohl.c index dfadf80d8..8e500a5e3 100644 --- a/libc/inet/ntohl.c +++ b/libc/inet/ntohl.c @@ -6,55 +6,37 @@ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ -#include <stdint.h> -#include <endian.h> -#include <byteswap.h> +#include <netinet/in.h> -uint32_t ntohl (uint32_t x); -uint16_t ntohs (uint16_t x); -uint32_t htonl (uint32_t x); -uint16_t htons (uint16_t x); +#undef ntohl +#undef ntohs +#undef htonl +#undef htons -#if __BYTE_ORDER == __BIG_ENDIAN -uint32_t ntohl (uint32_t x) -{ - return x; -} - -uint16_t ntohs (uint16_t x) -{ - return x; -} - -uint32_t htonl (uint32_t x) -{ - return x; -} +#if __BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN +# error "You seem to have an unsupported byteorder" +#endif -uint16_t htons (uint16_t x) -{ - return x; -} -#elif __BYTE_ORDER == __LITTLE_ENDIAN uint32_t ntohl (uint32_t x) { +#if __BYTE_ORDER == __BIG_ENDIAN + return x; +#else return __bswap_32(x); +#endif } +libc_hidden_def(ntohl) +strong_alias(ntohl,htonl) +libc_hidden_def(htonl) uint16_t ntohs (uint16_t x) { - return __bswap_16(x); -} - -uint32_t htonl (uint32_t x) -{ - return __bswap_32(x); -} - -uint16_t htons (uint16_t x) -{ - return __bswap_16(x); -} +#if __BYTE_ORDER == __BIG_ENDIAN + return x; #else -#error "You seem to have an unsupported byteorder" + return __bswap_16(x); #endif +} +libc_hidden_def(ntohs) +strong_alias(ntohs,htons) +libc_hidden_def(htons) diff --git a/libc/inet/ntop.c b/libc/inet/ntop.c index f19556dcd..30dde6f9c 100644 --- a/libc/inet/ntop.c +++ b/libc/inet/ntop.c @@ -15,8 +15,6 @@ * SOFTWARE. */ -#define __FORCE_GLIBC -#include <features.h> #include <sys/param.h> #include <sys/types.h> #include <sys/socket.h> @@ -30,13 +28,6 @@ #include <string.h> #include <ctype.h> -/* Experimentally off - libc_hidden_proto(memcpy) */ -/* Experimentally off - libc_hidden_proto(memset) */ -/* Experimentally off - libc_hidden_proto(strchr) */ -/* Experimentally off - libc_hidden_proto(strcpy) */ -/* Experimentally off - libc_hidden_proto(strlen) */ -libc_hidden_proto(sprintf) -libc_hidden_proto(tolower) /* * WARNING: Don't even consider trying to compile this on a system where @@ -58,17 +49,19 @@ libc_hidden_proto(tolower) static const char * inet_ntop4(const u_char *src, char *dst, size_t size) { - char tmp[sizeof ("255.255.255.255") + 1] = "\0"; + char tmp[sizeof ("255.255.255.255") + 1]; int octet; int i; + tmp[0] = '\0'; + i = 0; for (octet = 0; octet <= 3; octet++) { #if 0 /* since src is unsigned char, it will never be > 255 ... */ if (src[octet] > 255) { - __set_errno (ENOSPC); - return (NULL); + __set_errno(ENOSPC); + return NULL; } #endif tmp[i++] = '0' + src[octet] / 100; @@ -83,9 +76,9 @@ inet_ntop4(const u_char *src, char *dst, size_t size) } tmp[i - 1] = '\0'; - if (strlen (tmp) > size) { - __set_errno (ENOSPC); - return (NULL); + if (strlen(tmp) > size) { + __set_errno(ENOSPC); + return NULL; } return strcpy(dst, tmp); @@ -112,7 +105,7 @@ inet_ntop6(const u_char *src, char *dst, size_t size) * to use pointer overlays. All the world's not a VAX. */ char tmp[sizeof ("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp; - struct { int base, len; } best, cur; + struct { int base, len; } best = { 0, 0 }, cur = { 0, 0 }; u_int words[8]; int i; @@ -168,7 +161,7 @@ inet_ntop6(const u_char *src, char *dst, size_t size) if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) - return (NULL); + return NULL; tp += strlen(tp); break; } @@ -183,8 +176,8 @@ inet_ntop6(const u_char *src, char *dst, size_t size) * Check for overflow, copy, and we're done. */ if ((size_t)(tp - tmp) > size) { - __set_errno (ENOSPC); - return (NULL); + __set_errno(ENOSPC); + return NULL; } return strcpy(dst, tmp); } @@ -216,25 +209,25 @@ inet_pton4(const char *src, u_char *dst) u_int new = *tp * 10 + (ch - '0'); if (new > 255) - return (0); + return 0; *tp = new; if (! saw_digit) { if (++octets > 4) - return (0); + return 0; saw_digit = 1; } } else if (ch == '.' && saw_digit) { if (octets == 4) - return (0); + return 0; *++tp = 0; saw_digit = 0; } else - return (0); + return 0; } if (octets < 4) - return (0); + return 0; memcpy(dst, tmp, 4); - return (1); + return 1; } /* int @@ -253,13 +246,6 @@ inet_pton4(const char *src, u_char *dst) #ifdef __UCLIBC_HAS_IPV6__ -/* We cannot use the macro version of tolower() or very bad - * things happen when '*src++' gets evaluated multiple times. - * So undef it here so we get the function version of tolower - * instead. - */ -#undef tolower - static int inet_pton6(const char *src, u_char *dst) { @@ -276,19 +262,20 @@ inet_pton6(const char *src, u_char *dst) /* Leading :: requires some special handling. */ if (*src == ':') if (*++src != ':') - return (0); + return 0; curtok = src; saw_xdigit = 0; val = 0; - while ((ch = tolower (*src++)) != '\0') { + while ((ch = *src++) != '\0') { const char *pch; - pch = strchr(xdigits, ch); + /* | 0x20 is cheap tolower(), valid for letters/numbers only */ + pch = strchr(xdigits, (ch | 0x20)); if (pch != NULL) { val <<= 4; val |= (pch - xdigits); if (val > 0xffff) - return (0); + return 0; saw_xdigit = 1; continue; } @@ -296,16 +283,16 @@ inet_pton6(const char *src, u_char *dst) curtok = src; if (!saw_xdigit) { if (colonp) - return (0); + return 0; colonp = tp; continue; - } else if (*src == '\0') { - return (0); } + if (*src == '\0') + return 0; if (tp + 2 > endp) - return (0); - *tp++ = (u_char) (val >> 8) & 0xff; - *tp++ = (u_char) val & 0xff; + return 0; + *tp++ = (u_char) (val >> 8); + *tp++ = (u_char) val; saw_xdigit = 0; val = 0; continue; @@ -316,13 +303,13 @@ inet_pton6(const char *src, u_char *dst) saw_xdigit = 0; break; /* '\0' was seen by inet_pton4(). */ } - return (0); + return 0; } if (saw_xdigit) { if (tp + 2 > endp) - return (0); - *tp++ = (u_char) (val >> 8) & 0xff; - *tp++ = (u_char) val & 0xff; + return 0; + *tp++ = (u_char) (val >> 8); + *tp++ = (u_char) val; } if (colonp != NULL) { /* @@ -333,7 +320,7 @@ inet_pton6(const char *src, u_char *dst) int i; if (tp == endp) - return (0); + return 0; for (i = 1; i <= n; i++) { endp[- i] = colonp[n - i]; colonp[n - i] = 0; @@ -341,9 +328,9 @@ inet_pton6(const char *src, u_char *dst) tp = endp; } if (tp != endp) - return (0); + return 0; memcpy(dst, tmp, 16); - return (1); + return 1; } #endif /* __UCLIBC_HAS_IPV6__ */ @@ -358,20 +345,19 @@ inet_pton6(const char *src, u_char *dst) * author: * Paul Vixie, 1996. */ -libc_hidden_proto(inet_ntop) const char * inet_ntop(int af, const void *src, char *dst, socklen_t size) { switch (af) { case AF_INET: - return (inet_ntop4(src, dst, size)); + return inet_ntop4(src, dst, size); #ifdef __UCLIBC_HAS_IPV6__ case AF_INET6: - return (inet_ntop6(src, dst, size)); + return inet_ntop6(src, dst, size); #endif default: - __set_errno (EAFNOSUPPORT); - return (NULL); + __set_errno(EAFNOSUPPORT); + return NULL; } /* NOTREACHED */ } @@ -389,20 +375,19 @@ libc_hidden_def(inet_ntop) * author: * Paul Vixie, 1996. */ -libc_hidden_proto(inet_pton) int inet_pton(int af, const char *src, void *dst) { switch (af) { case AF_INET: - return (inet_pton4(src, dst)); + return inet_pton4(src, dst); #ifdef __UCLIBC_HAS_IPV6__ case AF_INET6: - return (inet_pton6(src, dst)); + return inet_pton6(src, dst); #endif default: - __set_errno (EAFNOSUPPORT); - return (-1); + __set_errno(EAFNOSUPPORT); + return -1; } /* NOTREACHED */ } diff --git a/libc/inet/opennameservers.c b/libc/inet/opennameservers.c index effd10800..576c8cae3 100644 --- a/libc/inet/opennameservers.c +++ b/libc/inet/opennameservers.c @@ -5,4 +5,4 @@ */ #define L_opennameservers -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/opensock.c b/libc/inet/opensock.c index a2c09dcf5..ac7289029 100644 --- a/libc/inet/opensock.c +++ b/libc/inet/opensock.c @@ -12,32 +12,25 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ -#include <assert.h> -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> #include <sys/socket.h> -#include <features.h> -#include <libc-internal.h> - -libc_hidden_proto(socket) +#include <bits/kernel-features.h> /* Return a socket of any type. The socket can be used in subsequent ioctl calls to talk to the kernel. */ int __opensock(void) attribute_hidden; int -__opensock (void) +__opensock(void) { - int fd; + int fd = -1; #ifdef __UCLIBC_HAS_IPV6__ - fd = socket(AF_INET6, SOCK_DGRAM, 0); - if (fd<0) -#endif /* __UCLIBC_HAS_IPV6__ */ - fd = socket(AF_INET, SOCK_DGRAM, 0); - return(fd); + fd = socket(AF_INET6, SOCK_DGRAM, 0); +#endif +#ifdef __UCLIBC_HAS_IPV4__ + if (fd < 0) + fd = socket(AF_INET, SOCK_DGRAM, 0); +#endif + return fd; } diff --git a/libc/inet/read_etc_hosts_r.c b/libc/inet/read_etc_hosts_r.c index 6504e541f..1ec74a50d 100644 --- a/libc/inet/read_etc_hosts_r.c +++ b/libc/inet/read_etc_hosts_r.c @@ -5,4 +5,4 @@ */ #define L_read_etc_hosts_r -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/res_comp.c b/libc/inet/res_comp.c index 8aee6b17c..51ea4f2e6 100644 --- a/libc/inet/res_comp.c +++ b/libc/inet/res_comp.c @@ -5,4 +5,4 @@ */ #define L_res_comp -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/res_data.c b/libc/inet/res_data.c new file mode 100644 index 000000000..b554b93db --- /dev/null +++ b/libc/inet/res_data.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_res_data +#include RESOLVER diff --git a/libc/inet/res_init.c b/libc/inet/res_init.c index 09caf4927..b1a175752 100644 --- a/libc/inet/res_init.c +++ b/libc/inet/res_init.c @@ -5,4 +5,4 @@ */ #define L_res_init -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/res_query.c b/libc/inet/res_query.c index c662510e6..f3e569fad 100644 --- a/libc/inet/res_query.c +++ b/libc/inet/res_query.c @@ -5,4 +5,4 @@ */ #define L_res_query -#include "resolv.c" +#include RESOLVER diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 1f12be9b9..f378c9b9d 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -1,3 +1,4 @@ +/* vi: set sw=4 ts=4: */ /* resolv.c: DNS Resolver * * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>, @@ -8,7 +9,6 @@ * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. */ - /* * Portions Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. @@ -37,7 +37,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ - /* * Portions Copyright (c) 1993 by Digital Equipment Corporation. * @@ -57,7 +56,6 @@ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ - /* * Portions Copyright (c) 1996-1999 by Internet Software Consortium. * @@ -74,32 +72,25 @@ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ - /* - * * 5-Oct-2000 W. Greathouse wgreathouse@smva.com - * Fix memory leak and memory corruption. - * -- Every name resolution resulted in - * a new parse of resolv.conf and new - * copy of nameservers allocated by - * strdup. - * -- Every name resolution resulted in - * a new read of resolv.conf without - * resetting index from prior read... - * resulting in exceeding array bounds. - * - * Limit nameservers read from resolv.conf - * - * Add "search" domains from resolv.conf + * Fix memory leak and memory corruption. + * -- Every name resolution resulted in + * a new parse of resolv.conf and new + * copy of nameservers allocated by + * strdup. + * -- Every name resolution resulted in + * a new read of resolv.conf without + * resetting index from prior read... + * resulting in exceeding array bounds. * - * Some systems will return a security - * signature along with query answer for - * dynamic DNS entries. - * -- skip/ignore this answer - * - * Include arpa/nameser.h for defines. - * - * General cleanup + * Limit nameservers read from resolv.conf. + * Add "search" domains from resolv.conf. + * Some systems will return a security + * signature along with query answer for + * dynamic DNS entries -- skip/ignore this answer. + * Include arpa/nameser.h for defines. + * General cleanup. * * 20-Jun-2001 Michal Moskal <malekith@pld.org.pl> * partial IPv6 support (i.e. gethostbyname2() and resolve_address2() @@ -131,13 +122,182 @@ * 7-Sep-2004 Erik Andersen <andersen@codepoet.org> * Added gethostent_r() * + * 2008, 2009 Denys Vlasenko <vda.linux@googlemail.com> + * Cleanups, fixes, readability, more cleanups and more fixes. + * + * March 2010 Bernhard Reutner-Fischer + * Switch to common config parser + */ +/* Nota bene: + * The whole resolver code has several (severe) problems: + * - it doesn't even build without IPv4, i.e. !UCLIBC_HAS_IPV4 but only IPv6 + * - it is way too big + * + * Both points above are considered bugs, patches/reimplementations welcome. + */ +/* RFC 1035 +... +Whenever an octet represents a numeric quantity, the left most bit +in the diagram is the high order or most significant bit. +That is, the bit labeled 0 is the most significant bit. +... + +4.1.1. Header section format + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ID | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + |QR| OPCODE |AA|TC|RD|RA| 0 0 0| RCODE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QDCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ANCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | NSCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ARCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +ID 16 bit random identifier assigned by querying peer. + Used to match query/response. +QR message is a query (0), or a response (1). +OPCODE 0 standard query (QUERY) + 1 inverse query (IQUERY) + 2 server status request (STATUS) +AA Authoritative Answer - this bit is valid in responses. + Responding name server is an authority for the domain name + in question section. Answer section may have multiple owner names + because of aliases. The AA bit corresponds to the name which matches + the query name, or the first owner name in the answer section. +TC TrunCation - this message was truncated. +RD Recursion Desired - this bit may be set in a query and + is copied into the response. If RD is set, it directs + the name server to pursue the query recursively. + Recursive query support is optional. +RA Recursion Available - this be is set or cleared in a + response, and denotes whether recursive query support is + available in the name server. +RCODE Response code. + 0 No error condition + 1 Format error + 2 Server failure - server was unable to process the query + due to a problem with the name server. + 3 Name Error - meaningful only for responses from + an authoritative name server. The referenced domain name + does not exist. + 4 Not Implemented. + 5 Refused. +QDCOUNT number of entries in the question section. +ANCOUNT number of records in the answer section. +NSCOUNT number of records in the authority records section. +ARCOUNT number of records in the additional records section. + +4.1.2. Question section format + +The section contains QDCOUNT (usually 1) entries, each of this format: + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / QNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QTYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QCLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +QNAME a domain name represented as a sequence of labels, where + each label consists of a length octet followed by that + number of octets. The domain name terminates with the + zero length octet for the null label of the root. Note + that this field may be an odd number of octets; no + padding is used. +QTYPE a two octet type of the query. + 1 a host address [REQ_A const] + 2 an authoritative name server + 3 a mail destination (Obsolete - use MX) + 4 a mail forwarder (Obsolete - use MX) + 5 the canonical name for an alias + 6 marks the start of a zone of authority + 7 a mailbox domain name (EXPERIMENTAL) + 8 a mail group member (EXPERIMENTAL) + 9 a mail rename domain name (EXPERIMENTAL) + 10 a null RR (EXPERIMENTAL) + 11 a well known service description + 12 a domain name pointer [REQ_PTR const] + 13 host information + 14 mailbox or mail list information + 15 mail exchange + 16 text strings + 0x1c IPv6? + 252 a request for a transfer of an entire zone + 253 a request for mailbox-related records (MB, MG or MR) + 254 a request for mail agent RRs (Obsolete - see MX) + 255 a request for all records +QCLASS a two octet code that specifies the class of the query. + 1 the Internet + (others are historic only) + 255 any class + +4.1.3. Resource record format + +The answer, authority, and additional sections all share the same format: +a variable number of resource records, where the number of records +is specified in the corresponding count field in the header. +Each resource record has this format: + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / / + / NAME / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | CLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TTL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RDLENGTH | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| + / RDATA / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +NAME a domain name to which this resource record pertains. +TYPE two octets containing one of the RR type codes. This + field specifies the meaning of the data in the RDATA field. +CLASS two octets which specify the class of the data in the RDATA field. +TTL a 32 bit unsigned integer that specifies the time interval + (in seconds) that the record may be cached. +RDLENGTH a 16 bit integer, length in octets of the RDATA field. +RDATA a variable length string of octets that describes the resource. + The format of this information varies according to the TYPE + and CLASS of the resource record. + If the TYPE is A and the CLASS is IN, it's a 4 octet IP address. + +4.1.4. Message compression + +In order to reduce the size of messages, domain names can be compressed. +An entire domain name or a list of labels at the end of a domain name +is replaced with a pointer to a prior occurance of the same name. + +The pointer takes the form of a two octet sequence: + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 1 1| OFFSET | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +The first two bits are ones. This allows a pointer to be distinguished +from a label, since the label must begin with two zero bits because +labels are restricted to 63 octets or less. The OFFSET field specifies +an offset from the start of the message (i.e., the first octet +of the ID field in the domain header). +A zero offset specifies the first byte of the ID field, etc. +Domain name in a message can be represented as either: + - a sequence of labels ending in a zero octet + - a pointer + - a sequence of labels ending with a pointer */ -#define __FORCE_GLIBC -#include <features.h> #include <string.h> #include <stdio.h> +#include <stdio_ext.h> #include <signal.h> +#include <malloc.h> #include <errno.h> #include <sys/poll.h> #include <sys/socket.h> @@ -151,10 +311,14 @@ #include <netdb.h> #include <ctype.h> #include <stdbool.h> +#include <time.h> #include <arpa/nameser.h> #include <sys/utsname.h> #include <sys/un.h> +#include <sys/stat.h> +#include <sys/param.h> #include <bits/uClibc_mutex.h> +#include "internal/parse_config.h" /* poll() is not supported in kernel <= 2.0, therefore if __NR_poll is * not available, we assume an old Linux kernel is in use and we will @@ -164,74 +328,21 @@ # define USE_SELECT #endif -__UCLIBC_MUTEX_EXTERN(__resolv_lock); - -/* Experimentally off - libc_hidden_proto(memcpy) */ -/* Experimentally off - libc_hidden_proto(memset) */ -/* Experimentally off - libc_hidden_proto(memmove) */ -/* Experimentally off - libc_hidden_proto(strchr) */ -/* Experimentally off - libc_hidden_proto(strcmp) */ -/* Experimentally off - libc_hidden_proto(strcpy) */ -/* Experimentally off - libc_hidden_proto(strdup) */ -/* Experimentally off - libc_hidden_proto(strlen) */ -/* Experimentally off - libc_hidden_proto(strncat) */ -/* Experimentally off - libc_hidden_proto(strncpy) */ -/* libc_hidden_proto(strnlen) */ -/* Experimentally off - libc_hidden_proto(strstr) */ -/* Experimentally off - libc_hidden_proto(strcasecmp) */ -libc_hidden_proto(socket) -libc_hidden_proto(close) -libc_hidden_proto(fopen) -libc_hidden_proto(fclose) -libc_hidden_proto(random) -libc_hidden_proto(getservbyport) -libc_hidden_proto(uname) -libc_hidden_proto(inet_addr) -libc_hidden_proto(inet_aton) -libc_hidden_proto(inet_pton) -libc_hidden_proto(inet_ntop) -libc_hidden_proto(connect) -libc_hidden_proto(poll) -libc_hidden_proto(select) -libc_hidden_proto(recv) -libc_hidden_proto(send) -libc_hidden_proto(printf) -libc_hidden_proto(sprintf) -libc_hidden_proto(snprintf) -libc_hidden_proto(fgets) -libc_hidden_proto(gethostbyname) -libc_hidden_proto(gethostbyname_r) -libc_hidden_proto(gethostbyname2_r) -libc_hidden_proto(gethostbyaddr) -libc_hidden_proto(gethostbyaddr_r) -libc_hidden_proto(ns_name_uncompress) -libc_hidden_proto(ns_name_unpack) -libc_hidden_proto(ns_name_ntop) -libc_hidden_proto(res_init) -libc_hidden_proto(res_query) -libc_hidden_proto(res_querydomain) -libc_hidden_proto(gethostent_r) -libc_hidden_proto(fprintf) -libc_hidden_proto(__h_errno_location) -#ifdef __UCLIBC_HAS_XLOCALE__ -libc_hidden_proto(__ctype_b_loc) -#elif defined __UCLIBC_HAS_CTYPE_TABLES__ -libc_hidden_proto(__ctype_b) +#if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ +#define IF_HAS_BOTH(...) __VA_ARGS__ +#else +#define IF_HAS_BOTH(...) #endif -int __libc_getdomainname(char *name, size_t len); -libc_hidden_proto(__libc_getdomainname) -#define MAX_RECURSE 5 -#define REPLY_TIMEOUT 10 -#define MAX_RETRIES 3 -#define MAX_SERVERS 3 -#define MAX_SEARCH 4 - -#define MAX_ALIASES 5 - +#define MAX_RECURSE 5 +#define MAXALIASES (4) /* 1:ip + 1:full + MAX_ALIASES:aliases + 1:NULL */ -#define ALIAS_DIM (2 + MAX_ALIASES + 1) +#define ALIAS_DIM (2 + MAXALIASES + 1) +#define BUFSZ (80) /* one line */ + +#define NS_TYPE_ELT 0x40 /*%< EDNS0 extended label type */ +#define DNS_LABELTYPE_BITSTRING 0x41 #undef DEBUG /* #define DEBUG */ @@ -240,7 +351,7 @@ libc_hidden_proto(__libc_getdomainname) #define DPRINTF(X,args...) fprintf(stderr, X, ##args) #else #define DPRINTF(X,args...) -#endif /* DEBUG */ +#endif /* Make sure the incoming char * buffer is aligned enough to handle our random * structures. This define is the same as we use for malloc alignment (which @@ -251,18 +362,10 @@ libc_hidden_proto(__libc_getdomainname) #define ALIGN_BUFFER_OFFSET(buf) ((ALIGN_ATTR - ((size_t)buf % ALIGN_ATTR)) % ALIGN_ATTR) -/* Global stuff (stuff needing to be locked to be thread safe)... */ -extern int __nameservers attribute_hidden; -extern char * __nameserver[MAX_SERVERS] attribute_hidden; -extern int __searchdomains attribute_hidden; -extern char * __searchdomain[MAX_SEARCH] attribute_hidden; - - - /* Structs */ struct resolv_header { int id; - int qr,opcode,aa,tc,rd,ra,rcode; + int qr, opcode, aa, tc, rd, ra, rcode; int qdcount; int ancount; int nscount; @@ -270,18 +373,18 @@ struct resolv_header { }; struct resolv_question { - char * dotted; + char *dotted; int qtype; int qclass; }; struct resolv_answer { - char * dotted; + char *dotted; int atype; int aclass; int ttl; int rdlength; - const unsigned char * rdata; + const unsigned char *rdata; int rdoffset; char* buf; size_t buflen; @@ -294,49 +397,178 @@ enum etc_hosts_action { GET_HOSTS_BYADDR, }; -/* function prototypes */ -extern int __get_hosts_byname_r(const char * name, int type, - struct hostent * result_buf, - char * buf, size_t buflen, - struct hostent ** result, - int * h_errnop) attribute_hidden; -extern int __get_hosts_byaddr_r(const char * addr, int len, int type, - struct hostent * result_buf, - char * buf, size_t buflen, - struct hostent ** result, - int * h_errnop) attribute_hidden; -extern FILE * __open_etc_hosts(void) attribute_hidden; -extern int __read_etc_hosts_r(FILE *fp, const char * name, int type, - enum etc_hosts_action action, - struct hostent * result_buf, - char * buf, size_t buflen, - struct hostent ** result, - int * h_errnop) attribute_hidden; -extern int __dns_lookup(const char * name, int type, int nscount, - char ** nsip, unsigned char ** outpacket, struct resolv_answer * a) attribute_hidden; - -extern int __encode_dotted(const char * dotted, unsigned char * dest, int maxlen) attribute_hidden; -extern int __decode_dotted(const unsigned char * const message, int offset, - char * dest, int maxlen) attribute_hidden; -extern int __length_dotted(const unsigned char * const message, int offset) attribute_hidden; -extern int __encode_header(struct resolv_header * h, unsigned char * dest, int maxlen) attribute_hidden; -extern int __decode_header(unsigned char * data, struct resolv_header * h) attribute_hidden; -extern int __encode_question(const struct resolv_question * const q, - unsigned char * dest, int maxlen) attribute_hidden; -extern int __decode_question(const unsigned char * const message, int offset, - struct resolv_question * q) attribute_hidden; -extern int __encode_answer(struct resolv_answer * a, - unsigned char * dest, int maxlen) attribute_hidden; -extern int __decode_answer(const unsigned char * message, int offset, - struct resolv_answer * a) attribute_hidden; -extern int __length_question(const unsigned char * const message, int offset) attribute_hidden; +typedef union sockaddr46_t { + struct sockaddr sa; +#ifdef __UCLIBC_HAS_IPV4__ + struct sockaddr_in sa4; +#endif +#ifdef __UCLIBC_HAS_IPV6__ + struct sockaddr_in6 sa6; +#endif +} sockaddr46_t; + + +__UCLIBC_MUTEX_EXTERN(__resolv_lock) attribute_hidden; + +/* Protected by __resolv_lock */ +extern void (*__res_sync)(void) attribute_hidden; +/*extern uint32_t __resolv_opts attribute_hidden; */ +extern uint8_t __resolv_timeout attribute_hidden; +extern uint8_t __resolv_attempts attribute_hidden; +extern unsigned __nameservers attribute_hidden; +extern unsigned __searchdomains attribute_hidden; +extern sockaddr46_t *__nameserver attribute_hidden; +extern char **__searchdomain attribute_hidden; +#ifdef __UCLIBC_HAS_IPV4__ +extern const struct sockaddr_in __local_nameserver attribute_hidden; +#else +extern const struct sockaddr_in6 __local_nameserver attribute_hidden; +#endif +/* Arbitrary */ +#define MAXLEN_searchdomain 128 + + +/* prototypes for internal functions */ +extern void endhostent_unlocked(void) attribute_hidden; +extern int __get_hosts_byname_r(const char *name, + int type, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) attribute_hidden; +extern int __get_hosts_byaddr_r(const char *addr, + int len, + int type, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) attribute_hidden; +extern parser_t *__open_etc_hosts(void) attribute_hidden; +extern int __read_etc_hosts_r(parser_t *parser, + const char *name, + int type, + enum etc_hosts_action action, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) attribute_hidden; +extern int __dns_lookup(const char *name, + int type, + unsigned char **outpacket, + struct resolv_answer *a) attribute_hidden; +extern int __encode_dotted(const char *dotted, + unsigned char *dest, + int maxlen) attribute_hidden; +extern int __decode_dotted(const unsigned char *packet, + int offset, + int packet_len, + char *dest, + int dest_len) attribute_hidden; +extern int __encode_header(struct resolv_header *h, + unsigned char *dest, + int maxlen) attribute_hidden; +extern void __decode_header(unsigned char *data, + struct resolv_header *h) attribute_hidden; +extern int __encode_question(const struct resolv_question *q, + unsigned char *dest, + int maxlen) attribute_hidden; +extern int __encode_answer(struct resolv_answer *a, + unsigned char *dest, + int maxlen) attribute_hidden; extern void __open_nameservers(void) attribute_hidden; extern void __close_nameservers(void) attribute_hidden; -extern int __dn_expand(const u_char *, const u_char *, const u_char *, - char *, int); + +/* + * Theory of operation. + * + * gethostbyname, getaddrinfo and friends end up here, and they sometimes + * need to talk to DNS servers. In order to do this, we need to read /etc/resolv.conf + * and determine servers' addresses and the like. resolv.conf format: + * + * nameserver <IP[v6]> + * Address of DNS server. Cumulative. + * If not specified, assumed to be on localhost. + * search <domain1>[ <domain2>]... + * Append these domains to unqualified names. + * See ndots:n option. + * $LOCALDOMAIN (space-separated list) overrides this. + * domain <domain> + * Effectively same as "search" with one domain. + * If no "domain" line is present, the domain is determined + * from the local host name returned by gethostname(); + * the domain part is taken to be everything after the first dot. + * If there are no dots, there will be no "domain". + * The domain and search keywords are mutually exclusive. + * If more than one instance of these keywords is present, + * the last instance wins. + * sortlist 130.155.160.0[/255.255.240.0] 130.155.0.0 + * Allows addresses returned by gethostbyname to be sorted. + * Not supported. + * options option[ option]... + * (so far we support timeout:n and attempts:n) + * $RES_OPTIONS (space-separated list) is to be added to "options" + * debug sets RES_DEBUG in _res.options + * ndots:n how many dots there should be so that name will be tried + * first as an absolute name before any search list elements + * are appended to it. Default 1 + * timeout:n how long to wait for response. Default 5 + * (sun seems to have retrans:n synonym) + * attempts:n number of rounds to do before giving up and returning + * an error. Default 2 + * (sun seems to have retry:n synonym) + * rotate sets RES_ROTATE in _res.options, round robin + * selection of nameservers. Otherwise try + * the first listed server first every time + * no-check-names + * sets RES_NOCHECKNAME in _res.options, which disables + * checking of incoming host names for invalid characters + * such as underscore (_), non-ASCII, or control characters + * inet6 sets RES_USE_INET6 in _res.options. Try a AAAA query + * before an A query inside the gethostbyname(), and map + * IPv4 responses in IPv6 "tunnelled form" if no AAAA records + * are found but an A record set exists + * no_tld_query (FreeBSDism?) + * do not attempt to resolve names without dots + * + * We will read and analyze /etc/resolv.conf as needed before + * we do a DNS request. This happens in __dns_lookup. + * It is reread if its mtime is changed. + * + * BSD has res_init routine which is used to initialize resolver state + * which is held in global structure _res. + * Generally, programs call res_init, then fiddle with _res.XXX + * (_res.options and _res.nscount, _res.nsaddr_list[N] + * are popular targets of fiddling) and expect subsequent calls + * to gethostbyname, getaddrinfo, etc to use modified information. + * + * However, historical _res structure is quite awkward. + * Using it for storing /etc/resolv.conf info is not desirable, + * and __dns_lookup does not use it. + * + * We would like to avoid using it unless absolutely necessary. + * If user doesn't use res_init, we should arrange it so that + * _res structure doesn't even *get linked in* into user's application + * (imagine static uclibc build here). + * + * The solution is a __res_sync function pointer, which is normally NULL. + * But if res_init is called, it gets set and any subsequent gethostbyname + * et al "syncronizes" our internal structures with potentially + * modified _res.XXX stuff by calling __res_sync. + * The trick here is that if res_init is not used and not linked in, + * gethostbyname itself won't reference _res and _res won't be linked in + * either. Other possible methods like + * if (__res_sync_just_an_int_flag) + * __sync_me_with_res() + * would pull in __sync_me_with_res, which pulls in _res. Bad. + */ + #ifdef L_encodeh -int attribute_hidden __encode_header(struct resolv_header *h, unsigned char *dest, int maxlen) + +int __encode_header(struct resolv_header *h, unsigned char *dest, int maxlen) { if (maxlen < HFIXEDSZ) return -1; @@ -360,10 +592,13 @@ int attribute_hidden __encode_header(struct resolv_header *h, unsigned char *des return HFIXEDSZ; } -#endif +#endif /* L_encodeh */ + #ifdef L_decodeh -int attribute_hidden __decode_header(unsigned char *data, struct resolv_header *h) + +void __decode_header(unsigned char *data, + struct resolv_header *h) { h->id = (data[0] << 8) | data[1]; h->qr = (data[2] & 0x80) ? 1 : 0; @@ -377,17 +612,16 @@ int attribute_hidden __decode_header(unsigned char *data, struct resolv_header * h->ancount = (data[6] << 8) | data[7]; h->nscount = (data[8] << 8) | data[9]; h->arcount = (data[10] << 8) | data[11]; - - return HFIXEDSZ; } -#endif +#endif /* L_decodeh */ + #ifdef L_encoded + /* Encode a dotted string into nameserver transport-level encoding. This routine is fairly dumb, and doesn't attempt to compress the data */ - -int attribute_hidden __encode_dotted(const char *dotted, unsigned char *dest, int maxlen) +int __encode_dotted(const char *dotted, unsigned char *dest, int maxlen) { unsigned used = 0; @@ -406,10 +640,9 @@ int attribute_hidden __encode_dotted(const char *dotted, unsigned char *dest, in memcpy(dest + used, dotted, l); used += l; - if (c) - dotted = c + 1; - else + if (!c) break; + dotted = c + 1; } if (maxlen < 1) @@ -419,49 +652,68 @@ int attribute_hidden __encode_dotted(const char *dotted, unsigned char *dest, in return used; } -#endif +#endif /* L_encoded */ + #ifdef L_decoded + /* Decode a dotted string from nameserver transport-level encoding. This routine understands compressed data. */ - -int attribute_hidden __decode_dotted(const unsigned char * const data, int offset, - char *dest, int maxlen) +int __decode_dotted(const unsigned char *packet, + int offset, + int packet_len, + char *dest, + int dest_len) { - int l; + unsigned b; bool measure = 1; unsigned total = 0; unsigned used = 0; + unsigned maxiter = 256; - if (!data) + if (!packet) return -1; - while ((l = data[offset++])) { + dest[0] = '\0'; + while (--maxiter) { + if (offset >= packet_len) + return -1; + b = packet[offset++]; + if (b == 0) + break; + if (measure) total++; - if ((l & 0xc0) == (0xc0)) { + + if ((b & 0xc0) == 0xc0) { + if (offset >= packet_len) + return -1; if (measure) total++; /* compressed item, redirect */ - offset = ((l & 0x3f) << 8) | data[offset]; + offset = ((b & 0x3f) << 8) | packet[offset]; measure = 0; continue; } - if ((used + l + 1) >= maxlen) + if (used + b + 1 >= dest_len) + return -1; + if (offset + b >= packet_len) return -1; + memcpy(dest + used, packet + offset, b); + offset += b; + used += b; - memcpy(dest + used, data + offset, l); - offset += l; - used += l; if (measure) - total += l; + total += b; - if (data[offset] != 0) + if (packet[offset] != 0) dest[used++] = '.'; else dest[used++] = '\0'; } + if (!maxiter) + return -1; /* The null byte must be counted too */ if (measure) @@ -471,34 +723,14 @@ int attribute_hidden __decode_dotted(const unsigned char * const data, int offse return total; } -#endif +#endif /* L_decoded */ -#ifdef L_lengthd -int attribute_hidden __length_dotted(const unsigned char * const data, int offset) -{ - int orig_offset = offset; - int l; - - if (!data) - return -1; - - while ((l = data[offset++])) { - - if ((l & 0xc0) == (0xc0)) { - offset++; - break; - } - - offset += l; - } - - return offset - orig_offset; -} -#endif #ifdef L_encodeq -int attribute_hidden __encode_question(const struct resolv_question * const q, - unsigned char *dest, int maxlen) + +int __encode_question(const struct resolv_question *q, + unsigned char *dest, + int maxlen) { int i; @@ -519,44 +751,12 @@ int attribute_hidden __encode_question(const struct resolv_question * const q, return i + 4; } -#endif +#endif /* L_encodeq */ -#ifdef L_decodeq -int attribute_hidden __decode_question(const unsigned char * const message, int offset, - struct resolv_question *q) -{ - char temp[256]; - int i; - - i = __decode_dotted(message, offset, temp, sizeof(temp)); - if (i < 0) - return i; - - offset += i; - - q->dotted = strdup(temp); /* TODO: what if this fails? */ - q->qtype = (message[offset + 0] << 8) | message[offset + 1]; - q->qclass = (message[offset + 2] << 8) | message[offset + 3]; - - return i + 4; -} -#endif - -#ifdef L_lengthq -int attribute_hidden __length_question(const unsigned char * const message, int offset) -{ - int i; - - i = __length_dotted(message, offset); - if (i < 0) - return i; - - return i + 4; -} -#endif #ifdef L_encodea -int attribute_hidden __encode_answer(struct resolv_answer *a, unsigned char *dest, int maxlen) + +int __encode_answer(struct resolv_answer *a, unsigned char *dest, int maxlen) { int i; @@ -584,53 +784,24 @@ int attribute_hidden __encode_answer(struct resolv_answer *a, unsigned char *des return i + RRFIXEDSZ + a->rdlength; } -#endif - -#ifdef L_decodea -int attribute_hidden __decode_answer(const unsigned char *message, int offset, - struct resolv_answer *a) -{ - char temp[256]; - int i; +#endif /* L_encodea */ - i = __decode_dotted(message, offset, temp, sizeof(temp)); - if (i < 0) - return i; - - message += offset + i; - - a->dotted = strdup(temp); /* TODO: what if this fails? */ - a->atype = (message[0] << 8) | message[1]; - message += 2; - a->aclass = (message[0] << 8) | message[1]; - message += 2; - a->ttl = (message[0] << 24) | - (message[1] << 16) | (message[2] << 8) | (message[3] << 0); - message += 4; - a->rdlength = (message[0] << 8) | message[1]; - message += 2; - a->rdata = message; - a->rdoffset = offset + i + RRFIXEDSZ; - - DPRINTF("i=%d,rdlength=%d\n", i, a->rdlength); - - return i + RRFIXEDSZ + a->rdlength; -} -#endif +#ifdef CURRENTLY_UNUSED #ifdef L_encodep + int __encode_packet(struct resolv_header *h, - struct resolv_question **q, - struct resolv_answer **an, - struct resolv_answer **ns, - struct resolv_answer **ar, - unsigned char *dest, int maxlen) attribute_hidden; + struct resolv_question **q, + struct resolv_answer **an, + struct resolv_answer **ns, + struct resolv_answer **ar, + unsigned char *dest, int maxlen) attribute_hidden; int __encode_packet(struct resolv_header *h, - struct resolv_question **q, - struct resolv_answer **an, - struct resolv_answer **ns, - struct resolv_answer **ar, - unsigned char *dest, int maxlen) + struct resolv_question **q, + struct resolv_answer **an, + struct resolv_answer **ns, + struct resolv_answer **ar, + unsigned char *dest, int maxlen) { int i, total = 0; unsigned j; @@ -679,20 +850,32 @@ int __encode_packet(struct resolv_header *h, return total; } -#endif +#endif /* L_encodep */ + #ifdef L_decodep + int __decode_packet(unsigned char *data, struct resolv_header *h) attribute_hidden; int __decode_packet(unsigned char *data, struct resolv_header *h) { - return __decode_header(data, h); + __decode_header(data, h); + return HFIXEDSZ; } -#endif +#endif /* L_decodep */ + #ifdef L_formquery -int __form_query(int id, const char *name, int type, unsigned char *packet, int maxlen); -int __form_query(int id, const char *name, int type, unsigned char *packet, - int maxlen) + +int __form_query(int id, + const char *name, + int type, + unsigned char *packet, + int maxlen) attribute_hidden; +int __form_query(int id, + const char *name, + int type, + unsigned char *packet, + int maxlen) { struct resolv_header h; struct resolv_question q; @@ -716,24 +899,355 @@ int __form_query(int id, const char *name, int type, unsigned char *packet, return i + j; } +#endif /* L_formquery */ +#endif /* CURRENTLY_UNUSED */ + + +#ifdef L_opennameservers + +# if __BYTE_ORDER == __LITTLE_ENDIAN +#define NAMESERVER_PORT_N (__bswap_constant_16(NAMESERVER_PORT)) +#else +#define NAMESERVER_PORT_N NAMESERVER_PORT +#endif + +__UCLIBC_MUTEX_INIT(__resolv_lock, PTHREAD_MUTEX_INITIALIZER); + +/* Protected by __resolv_lock */ +void (*__res_sync)(void); +/*uint32_t __resolv_opts; */ +uint8_t __resolv_timeout = RES_TIMEOUT; +uint8_t __resolv_attempts = RES_DFLRETRY; +unsigned __nameservers; +unsigned __searchdomains; +sockaddr46_t *__nameserver; +char **__searchdomain; +#ifdef __UCLIBC_HAS_IPV4__ +const struct sockaddr_in __local_nameserver = { + .sin_family = AF_INET, + .sin_port = NAMESERVER_PORT_N, +}; +#else +const struct sockaddr_in6 __local_nameserver = { + .sin6_family = AF_INET6, + .sin6_port = NAMESERVER_PORT_N, +}; +#endif + +/* Helpers. Both stop on EOL, if it's '\n', it is converted to NUL first */ +static char *skip_nospace(char *p) +{ + while (*p != '\0' && !isspace(*p)) { + if (*p == '\n') { + *p = '\0'; + break; + } + p++; + } + return p; +} +static char *skip_and_NUL_space(char *p) +{ + /* NB: '\n' is not isspace! */ + while (1) { + char c = *p; + if (c == '\0' || !isspace(c)) + break; + *p = '\0'; + if (c == '\n' || c == '#') + break; + p++; + } + return p; +} + +/* Must be called under __resolv_lock. */ +void __open_nameservers(void) +{ + static uint32_t resolv_conf_mtime; + + char szBuffer[MAXLEN_searchdomain]; + FILE *fp; + int i; + sockaddr46_t sa; + + if (!__res_sync) { + /* Reread /etc/resolv.conf if it was modified. */ + struct stat sb; + if (stat(_PATH_RESCONF, &sb) != 0) + sb.st_mtime = 0; + if (resolv_conf_mtime != (uint32_t)sb.st_mtime) { + resolv_conf_mtime = sb.st_mtime; + __close_nameservers(); /* force config reread */ + } + } + + if (__nameservers) + goto sync; + + __resolv_timeout = RES_TIMEOUT; + __resolv_attempts = RES_DFLRETRY; + + fp = fopen(_PATH_RESCONF, "r"); +#ifdef FALLBACK_TO_CONFIG_RESOLVCONF + if (!fp) { + /* If we do not have a pre-populated /etc/resolv.conf then + try to use the one from /etc/config which exists on numerous + systems ranging from some uClinux to IRIX installations and + may be the only /etc dir that was mounted rw. */ + fp = fopen("/etc/config/resolv.conf", "r"); + } #endif + if (fp) { + while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) { + void *ptr; + char *keyword, *p; + + keyword = p = skip_and_NUL_space(szBuffer); + /* skip keyword */ + p = skip_nospace(p); + /* find next word */ + p = skip_and_NUL_space(p); + + if (strcmp(keyword, "nameserver") == 0) { + /* terminate IP addr */ + *skip_nospace(p) = '\0'; + memset(&sa, 0, sizeof(sa)); + if (0) /* nothing */; +#ifdef __UCLIBC_HAS_IPV6__ + else if (inet_pton(AF_INET6, p, &sa.sa6.sin6_addr) > 0) { + sa.sa6.sin6_family = AF_INET6; + sa.sa6.sin6_port = htons(NAMESERVER_PORT); + } +#endif +#ifdef __UCLIBC_HAS_IPV4__ + else if (inet_pton(AF_INET, p, &sa.sa4.sin_addr) > 0) { + sa.sa4.sin_family = AF_INET; + sa.sa4.sin_port = htons(NAMESERVER_PORT); + } +#endif + else + continue; /* garbage on this line */ + ptr = realloc(__nameserver, (__nameservers + 1) * sizeof(__nameserver[0])); + if (!ptr) + continue; + __nameserver = ptr; + __nameserver[__nameservers++] = sa; /* struct copy */ + continue; + } + if (strcmp(keyword, "domain") == 0 || strcmp(keyword, "search") == 0) { + char *p1; + + /* free old domains ("last 'domain' or 'search' wins" rule) */ + while (__searchdomains) + free(__searchdomain[--__searchdomains]); + /*free(__searchdomain);*/ + /*__searchdomain = NULL; - not necessary */ + next_word: + /* terminate current word */ + p1 = skip_nospace(p); + /* find next word (maybe) */ + p1 = skip_and_NUL_space(p1); + /* add it */ + ptr = realloc(__searchdomain, (__searchdomains + 1) * sizeof(__searchdomain[0])); + if (!ptr) + continue; + __searchdomain = ptr; + /* NB: strlen(p) <= MAXLEN_searchdomain) because szBuffer[] is smaller */ + ptr = strdup(p); + if (!ptr) + continue; + DPRINTF("adding search %s\n", (char*)ptr); + __searchdomain[__searchdomains++] = (char*)ptr; + p = p1; + if (*p) + goto next_word; + continue; + } + /* if (strcmp(keyword, "sortlist") == 0)... */ + if (strcmp(keyword, "options") == 0) { + char *p1; + uint8_t *what; + + if (p == NULL || (p1 = strchr(p, ':')) == NULL) + continue; + *p1++ = '\0'; + if (strcmp(p, "timeout") == 0) + what = &__resolv_timeout; + else if (strcmp(p, "attempts") == 0) + what = &__resolv_attempts; + else + continue; + *what = atoi(p1); + DPRINTF("option %s:%d\n", p, *what); + } + } + fclose(fp); + } + if (__nameservers == 0) { + /* Have to handle malloc failure! What a mess... + * And it's not only here, we need to be careful + * to never write into __nameserver[0] if it points + * to constant __local_nameserver, or free it. */ + __nameserver = malloc(sizeof(__nameserver[0])); + if (__nameserver) + memcpy(__nameserver, &__local_nameserver, sizeof(__local_nameserver)); + else + __nameserver = (void*) &__local_nameserver; + __nameservers++; + } + if (__searchdomains == 0) { + char buf[256]; + char *p; + i = gethostname(buf, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; + if (i == 0 && (p = strchr(buf, '.')) != NULL && p[1]) { + p = strdup(p + 1); + if (!p) + goto err; + __searchdomain = malloc(sizeof(__searchdomain[0])); + if (!__searchdomain) { + free(p); + goto err; + } + __searchdomain[0] = p; + __searchdomains++; + err: ; + } + } + DPRINTF("nameservers = %d\n", __nameservers); + + sync: + if (__res_sync) + __res_sync(); +} +#endif /* L_opennameservers */ + + +#ifdef L_closenameservers + +/* Must be called under __resolv_lock. */ +void __close_nameservers(void) +{ + if (__nameserver != (void*) &__local_nameserver) + free(__nameserver); + __nameserver = NULL; + __nameservers = 0; + while (__searchdomains) + free(__searchdomain[--__searchdomains]); + free(__searchdomain); + __searchdomain = NULL; + /*__searchdomains = 0; - already is */ +} +#endif /* L_closenameservers */ + + #ifdef L_dnslookup -__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); -/* Just for the record, having to lock __dns_lookup() just for these two globals - * is pretty lame. I think these two variables can probably be de-global-ized, - * which should eliminate the need for doing locking here... Needs a closer - * look anyways. */ -static int static_ns = 0; -/* uint16: minimizing rw data size, even if code grows a tiny bit. - * rw data costs more. */ -static uint16_t static_id = 1; +/* Helpers */ +static int __length_question(const unsigned char *data, int maxlen) +{ + const unsigned char *start; + unsigned b; + + if (!data) + return -1; -int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char **nsip, - unsigned char **outpacket, struct resolv_answer *a) + start = data; + while (1) { + if (maxlen <= 0) + return -1; + b = *data++; + if (b == 0) + break; + if ((b & 0xc0) == 0xc0) { + /* It's a "compressed" name. */ + data++; /* skip lsb of redirected offset */ + maxlen -= 2; + break; + } + data += b; + maxlen -= (b + 1); /* account for data++ above */ + } + /* Up to here we were skipping encoded name */ + + /* Account for QTYPE and QCLASS fields */ + if (maxlen < 4) + return -1; + return data - start + 2 + 2; +} + +static int __decode_answer(const unsigned char *message, /* packet */ + int offset, + int len, /* total packet len */ + struct resolv_answer *a) { - int i, j, len, fd, pos, rc; + char temp[256]; + int i; + + DPRINTF("decode_answer(start): off %d, len %d\n", offset, len); + i = __decode_dotted(message, offset, len, temp, sizeof(temp)); + if (i < 0) + return i; + + message += offset + i; + len -= i + RRFIXEDSZ + offset; + if (len < 0) { + DPRINTF("decode_answer: off %d, len %d, i %d\n", offset, len, i); + return len; + } + +/* TODO: what if strdup fails? */ + a->dotted = strdup(temp); + a->atype = (message[0] << 8) | message[1]; + message += 2; + a->aclass = (message[0] << 8) | message[1]; + message += 2; + a->ttl = (message[0] << 24) | + (message[1] << 16) | (message[2] << 8) | (message[3] << 0); + message += 4; + a->rdlength = (message[0] << 8) | message[1]; + message += 2; + a->rdata = message; + a->rdoffset = offset + i + RRFIXEDSZ; + + DPRINTF("i=%d,rdlength=%d\n", i, a->rdlength); + + if (len < a->rdlength) + return -1; + return i + RRFIXEDSZ + a->rdlength; +} + +/* On entry: + * a.buf(len) = auxiliary buffer for IP addresses after first one + * a.add_count = how many additional addresses are there already + * outpacket = where to save ptr to raw packet? can be NULL + * On exit: + * ret < 0: error, all other data is not valid + * ret >= 0: length of reply packet + * a.add_count & a.buf: updated + * a.rdlength: length of addresses (4 bytes for IPv4) + * *outpacket: updated (packet is malloced, you need to free it) + * a.rdata: points into *outpacket to 1st IP addr + * NB: don't pass outpacket == NULL if you need to use a.rdata! + * a.atype: type of query? + * a.dotted: which name we _actually_ used. May contain search domains + * appended. (why the filed is called "dotted" I have no idea) + * This is a malloced string. May be NULL because strdup failed. + */ +int __dns_lookup(const char *name, + int type, + unsigned char **outpacket, + struct resolv_answer *a) +{ + /* Protected by __resolv_lock: */ + static int last_ns_num = 0; + static uint16_t last_id = 1; + + int i, j, fd, rc; + int packet_len; + int name_len; #ifdef USE_SELECT struct timeval tv; fd_set fds; @@ -744,221 +1258,287 @@ int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char struct resolv_question q; struct resolv_answer ma; bool first_answer = 1; - unsigned retries = 0; - unsigned char * packet = malloc(PACKETSZ); - char *dns, *lookup = malloc(MAXDNAME); - int variant = -1; /* search domain to append, -1 - none */ - int local_ns = -1, local_id = -1; + int retries_left; + unsigned char *packet = malloc(PACKETSZ); + char *lookup; + int variant = -1; /* search domain to append, -1: none */ + int local_ns_num = -1; /* Nth server to use */ + int local_id = local_id; /* for compiler */ + int sdomains = 0; bool ends_with_dot; -#ifdef __UCLIBC_HAS_IPV6__ - bool v6; - struct sockaddr_in6 sa6; -#endif -#ifdef __UCLIBC_HAS_IPV4__ - struct sockaddr_in sa; -#endif + sockaddr46_t sa; fd = -1; - - if (!packet || !lookup || !nscount || !name[0]) + lookup = NULL; + name_len = strlen(name); + if ((unsigned)name_len >= MAXDNAME - MAXLEN_searchdomain - 2) + goto fail; /* paranoia */ + lookup = malloc(name_len + 1/*for '.'*/ + MAXLEN_searchdomain + 1); + if (!packet || !lookup || !name[0]) goto fail; + ends_with_dot = (name[name_len - 1] == '.'); + /* no strcpy! paranoia, user might change name[] under us */ + memcpy(lookup, name, name_len); DPRINTF("Looking up type %d answer for '%s'\n", type, name); + retries_left = 0; /* for compiler */ + do { + int pos; + unsigned reply_timeout; - ends_with_dot = (name[strlen(name) - 1] == '.'); - - /* Mess with globals while under lock */ - __UCLIBC_MUTEX_LOCK(mylock); - local_ns = static_ns % nscount; - local_id = static_id; - __UCLIBC_MUTEX_UNLOCK(mylock); - - while (retries < MAX_RETRIES) { - if (fd != -1) + if (fd != -1) { close(fd); + fd = -1; + } - memset(packet, 0, PACKETSZ); + /* Mess with globals while under lock */ + /* NB: even data *pointed to* by globals may vanish + * outside the locks. We should assume any and all + * globals can completely change between locked + * code regions. OTOH, this is rare, so we don't need + * to handle it "nicely" (do not skip servers, + * search domains, etc), we only need to ensure + * we do not SEGV, use freed+overwritten data + * or do other Really Bad Things. */ + __UCLIBC_MUTEX_LOCK(__resolv_lock); + __open_nameservers(); + if (type != T_PTR) { + sdomains = __searchdomains; + } + lookup[name_len] = '\0'; + if ((unsigned)variant < sdomains) { + /* lookup is name_len + 1 + MAXLEN_searchdomain + 1 long */ + /* __searchdomain[] is not bigger than MAXLEN_searchdomain */ + lookup[name_len] = '.'; + strcpy(&lookup[name_len + 1], __searchdomain[variant]); + } + /* first time? pick starting server etc */ + if (local_ns_num < 0) { + local_id = last_id; +/*TODO: implement /etc/resolv.conf's "options rotate" + (a.k.a. RES_ROTATE bit in _res.options) + local_ns_num = 0; + if (_res.options & RES_ROTATE) */ + local_ns_num = last_ns_num; + retries_left = __nameservers * __resolv_attempts; + } + if (local_ns_num >= __nameservers) + local_ns_num = 0; + local_id++; + local_id &= 0xffff; + /* write new values back while still under lock */ + last_id = local_id; + last_ns_num = local_ns_num; + /* struct copy */ + /* can't just take a pointer, __nameserver[x] + * is not safe to use outside of locks */ + sa = __nameserver[local_ns_num]; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + memset(packet, 0, PACKETSZ); memset(&h, 0, sizeof(h)); - ++local_id; - local_id &= 0xffff; + /* encode header */ h.id = local_id; h.qdcount = 1; h.rd = 1; - DPRINTF("encoding header\n", h.rd); - i = __encode_header(&h, packet, PACKETSZ); if (i < 0) goto fail; - strncpy(lookup, name, MAXDNAME); - __UCLIBC_MUTEX_LOCK(__resolv_lock); - /* nsip is really __nameserver[] which is a global that - needs to hold __resolv_lock before access!! */ - dns = nsip[local_ns]; -/* TODO: all future accesses to 'dns' are guarded by __resolv_lock too. - * Why? We already fetched nsip[local_ns] here, - * future changes to nsip[] by other threads cannot affect us. - * We can use 'dns' without locking. If I'm wrong, - * please explain in comments why locking is needed. */ - if (variant >= 0) { - if (variant < __searchdomains) { - strncat(lookup, ".", MAXDNAME); - strncat(lookup, __searchdomain[variant], MAXDNAME); - } - } - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - + /* encode question */ DPRINTF("lookup name: %s\n", lookup); - q.dotted = (char *)lookup; + q.dotted = lookup; q.qtype = type; q.qclass = C_IN; /* CLASS_IN */ - j = __encode_question(&q, packet+i, PACKETSZ-i); if (j < 0) goto fail; + packet_len = i + j; - len = i + j; - - DPRINTF("On try %d, sending query to port %d of machine %s\n", - retries+1, NAMESERVER_PORT, dns); - -#ifdef __UCLIBC_HAS_IPV6__ - __UCLIBC_MUTEX_LOCK(__resolv_lock); - /* 'dns' is really __nameserver[] which is a global that - needs to hold __resolv_lock before access!! */ - v6 = inet_pton(AF_INET6, dns, &sa6.sin6_addr) > 0; - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - fd = socket(v6 ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP); -#else - fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); -#endif - if (fd < 0) { - retries++; - continue; - } - - /* Connect to the UDP socket so that asyncronous errors are returned */ + /* send packet */ +#ifdef DEBUG + { + const socklen_t plen = sa.sa.sa_family == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN; + char *pbuf = malloc(plen); + if (pbuf == NULL) ;/* nothing */ #ifdef __UCLIBC_HAS_IPV6__ - if (v6) { - sa6.sin6_family = AF_INET6; - sa6.sin6_port = htons(NAMESERVER_PORT); - /* sa6.sin6_addr is already here */ - rc = connect(fd, (struct sockaddr *) &sa6, sizeof(sa6)); - } else { + else if (sa.sa.sa_family == AF_INET6) + pbuf = (char*)inet_ntop(AF_INET6, &sa.sa6.sin6_addr, pbuf, plen); #endif #ifdef __UCLIBC_HAS_IPV4__ - sa.sin_family = AF_INET; - sa.sin_port = htons(NAMESERVER_PORT); - __UCLIBC_MUTEX_LOCK(__resolv_lock); - /* 'dns' is really __nameserver[] which is a global that - needs to hold __resolv_lock before access!! */ - sa.sin_addr.s_addr = inet_addr(dns); - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - rc = connect(fd, (struct sockaddr *) &sa, sizeof(sa)); + else if (sa.sa.sa_family == AF_INET) + pbuf = (char*)inet_ntop(AF_INET, &sa.sa4.sin_addr, pbuf, plen); #endif -#ifdef __UCLIBC_HAS_IPV6__ + DPRINTF("On try %d, sending query to %s, port %d\n", + retries_left, pbuf, NAMESERVER_PORT); + free(pbuf); } #endif + fd = socket(sa.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) /* paranoia */ + goto try_next_server; + rc = connect(fd, &sa.sa, sizeof(sa)); if (rc < 0) { - if (errno == ENETUNREACH) { + /*if (errno == ENETUNREACH) { */ /* routing error, presume not transient */ - goto tryall; - } + goto try_next_server; + /*} */ +/*For example, what transient error this can be? Can't think of any */ /* retry */ - retries++; - continue; + /*continue; */ } - - DPRINTF("Transmitting packet of length %d, id=%d, qr=%d\n", - len, h.id, h.qr); - - send(fd, packet, len, 0); + DPRINTF("Xmit packet len:%d id:%d qr:%d\n", packet_len, h.id, h.qr); + /* no error check - if it fails, we time out on recv */ + send(fd, packet, packet_len, 0); #ifdef USE_SELECT + reply_timeout = __resolv_timeout; + wait_again: FD_ZERO(&fds); FD_SET(fd, &fds); - tv.tv_sec = REPLY_TIMEOUT; + tv.tv_sec = reply_timeout; tv.tv_usec = 0; if (select(fd + 1, &fds, NULL, NULL, &tv) <= 0) { DPRINTF("Timeout\n"); - - /* timed out, so retry send and receive, - * to next nameserver on queue */ - goto tryall; + /* timed out, so retry send and receive + * to next nameserver */ + goto try_next_server; } -#else + reply_timeout--; +#else /* !USE_SELECT */ + reply_timeout = __resolv_timeout * 1000; + wait_again: fds.fd = fd; fds.events = POLLIN; - if (poll(&fds, 1, REPLY_TIMEOUT * 1000) <= 0) { + if (poll(&fds, 1, reply_timeout) <= 0) { DPRINTF("Timeout\n"); - - /* timed out, so retry send and receive, - * to next nameserver on queue */ - goto tryall; + /* timed out, so retry send and receive + * to next nameserver */ + goto try_next_server; } + if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) { + DPRINTF("Bad event\n"); + goto try_next_server; + } +/*TODO: better timeout accounting?*/ + reply_timeout -= 1000; +#endif /* USE_SELECT */ + +/* vda: a bogus response seen in real world (caused SEGV in uclibc): + * "ping www.google.com" sending AAAA query and getting + * response with one answer... with answer part missing! + * Fixed by thorough checks for not going past the packet's end. + */ +#ifdef DEBUG + { + static const char test_query[32] = "\0\2\1\0\0\1\0\0\0\0\0\0\3www\6google\3com\0\0\34\0\1"; + static const char test_respn[32] = "\0\2\201\200\0\1\0\1\0\0\0\0\3www\6google\3com\0\0\34\0\1"; + pos = memcmp(packet + 2, test_query + 2, 30); + packet_len = recv(fd, packet, PACKETSZ, MSG_DONTWAIT); + if (pos == 0) { + packet_len = 32; + memcpy(packet + 2, test_respn + 2, 30); + } + } +#else + packet_len = recv(fd, packet, PACKETSZ, MSG_DONTWAIT); #endif - len = recv(fd, packet, PACKETSZ, 0); - if (len < HFIXEDSZ) { - /* too short ! */ - goto again; + if (packet_len < HFIXEDSZ) { + /* too short! + * If the peer did shutdown then retry later, + * try next peer on error. + * it's just a bogus packet from somewhere */ + bogus_packet: + if (packet_len >= 0 && reply_timeout) + goto wait_again; + goto try_next_server; } - __decode_header(packet, &h); - - DPRINTF("id = %d, qr = %d\n", h.id, h.qr); - - if ((h.id != local_id) || (!h.qr)) { + DPRINTF("len:%d id:%d qr:%d\n", packet_len, h.id, h.qr); + if (h.id != local_id || !h.qr) { /* unsolicited */ - goto again; + goto bogus_packet; } - DPRINTF("Got response %s\n", "(i think)!"); + DPRINTF("Got response (i think)!\n"); DPRINTF("qrcount=%d,ancount=%d,nscount=%d,arcount=%d\n", h.qdcount, h.ancount, h.nscount, h.arcount); DPRINTF("opcode=%d,aa=%d,tc=%d,rd=%d,ra=%d,rcode=%d\n", h.opcode, h.aa, h.tc, h.rd, h.ra, h.rcode); - if ((h.rcode) || (h.ancount < 1)) { - /* negative result, not present */ - goto again; + /* bug 660 says we treat negative response as an error + * and retry, which is, eh, an error. :) + * We were incurring long delays because of this. */ + if (h.rcode == NXDOMAIN || h.rcode == SERVFAIL) { + /* if possible, try next search domain */ + if (!ends_with_dot) { + DPRINTF("variant:%d sdomains:%d\n", variant, sdomains); + if (variant < sdomains - 1) { + /* next search domain */ + variant++; + continue; + } + /* no more search domains to try */ + } + if (h.rcode != SERVFAIL) { + /* dont loop, this is "no such host" situation */ + h_errno = HOST_NOT_FOUND; + goto fail1; + } } + /* Insert other non-fatal errors here, which do not warrant + * switching to next nameserver */ - pos = HFIXEDSZ; + /* Strange error, assuming this nameserver is feeling bad */ + if (h.rcode != 0) + goto try_next_server; + /* Code below won't work correctly with h.ancount == 0, so... */ + if (h.ancount <= 0) { + h_errno = NO_DATA; /* [is this correct code to check for?] */ + goto fail1; + } + pos = HFIXEDSZ; for (j = 0; j < h.qdcount; j++) { DPRINTF("Skipping question %d at %d\n", j, pos); - i = __length_question(packet, pos); - DPRINTF("Length of question %d is %d\n", j, i); - if (i < 0) - goto again; + i = __length_question(packet + pos, packet_len - pos); + if (i < 0) { + DPRINTF("Packet'question section " + "is truncated, trying next server\n"); + goto try_next_server; + } pos += i; + DPRINTF("Length of question %d is %d\n", j, i); } DPRINTF("Decoding answer at pos %d\n", pos); first_answer = 1; - for (j = 0; j < h.ancount; j++, pos += i) { - i = __decode_answer(packet, pos, &ma); - + a->dotted = NULL; + for (j = 0; j < h.ancount; j++) { + i = __decode_answer(packet, pos, packet_len, &ma); if (i < 0) { DPRINTF("failed decode %d\n", i); - goto again; + /* If the message was truncated but we have + * decoded some answers, pretend it's OK */ + if (j && h.tc) + break; + goto try_next_server; } + pos += i; if (first_answer) { ma.buf = a->buf; ma.buflen = a->buflen; ma.add_count = a->add_count; + free(a->dotted); memcpy(a, &ma, sizeof(ma)); - if (a->atype != T_SIG && (0 == a->buf || (type != T_A && type != T_AAAA))) + if (a->atype != T_SIG && (NULL == a->buf || (type != T_A && type != T_AAAA))) break; - if (a->atype != type) { - free(a->dotted); + if (a->atype != type) continue; - } a->add_count = h.ancount - j - 1; if ((a->rdlength + sizeof(struct in_addr*)) * a->add_count > a->buflen) break; @@ -972,846 +1552,223 @@ int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char free(a->dotted); DPRINTF("Answer address len(%u) differs from original(%u)\n", ma.rdlength, a->rdlength); - goto again; + goto try_next_server; } memcpy(a->buf + (a->add_count * ma.rdlength), ma.rdata, ma.rdlength); ++a->add_count; } } + /* Success! */ DPRINTF("Answer name = |%s|\n", a->dotted); DPRINTF("Answer type = |%d|\n", a->atype); - - close(fd); - + if (fd != -1) + close(fd); if (outpacket) *outpacket = packet; else free(packet); free(lookup); + return packet_len; - /* Mess with globals while under lock */ - __UCLIBC_MUTEX_LOCK(mylock); - static_ns = local_ns; - static_id = local_id; - __UCLIBC_MUTEX_UNLOCK(mylock); - - return len; /* success! */ - - tryall: - /* if there are other nameservers, give them a go, - otherwise return with error */ + try_next_server: + /* Try next nameserver */ + retries_left--; + local_ns_num++; variant = -1; - local_ns = (local_ns + 1) % nscount; - if (local_ns == 0) - retries++; - - continue; - - again: - /* if there are searchdomains, try them or fallback as passed */ - if (!ends_with_dot) { - int sdomains; - - __UCLIBC_MUTEX_LOCK(__resolv_lock); - sdomains = __searchdomains; - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - - if (variant < sdomains - 1) { - /* next search */ - variant++; - continue; - } - } - /* next server, first search */ - local_ns = (local_ns + 1) % nscount; - if (local_ns == 0) - retries++; - variant = -1; - } + } while (retries_left > 0); fail: + h_errno = NETDB_INTERNAL; + fail1: if (fd != -1) close(fd); free(lookup); free(packet); - h_errno = NETDB_INTERNAL; - /* Mess with globals while under lock */ - if (local_ns != -1) { - __UCLIBC_MUTEX_LOCK(mylock); - static_ns = local_ns; - static_id = local_id; - __UCLIBC_MUTEX_UNLOCK(mylock); - } return -1; } -#endif - -#ifdef L_opennameservers - -/* We use __resolv_lock to guard access to the - * '__nameservers' and __searchdomains globals */ -int __nameservers; -char * __nameserver[MAX_SERVERS]; -int __searchdomains; -char * __searchdomain[MAX_SEARCH]; +#endif /* L_dnslookup */ -__UCLIBC_MUTEX_INIT(__resolv_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); - -/* - * we currently read formats not quite the same as that on normal - * unix systems, we can have a list of nameservers after the keyword. - */ - -void attribute_hidden __open_nameservers(void) -{ - FILE *fp; - int i; -#define RESOLV_ARGS 5 - char szBuffer[128], *p, *argv[RESOLV_ARGS]; - int argc; - __UCLIBC_MUTEX_LOCK(__resolv_lock); - if (__nameservers > 0) - goto DONE; - - if ((fp = fopen("/etc/resolv.conf", "r")) || - (fp = fopen("/etc/config/resolv.conf", "r"))) - { - while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) { - for (p = szBuffer; *p && isspace(*p); p++) - /* skip white space */; - if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */ - continue; - argc = 0; - while (*p && argc < RESOLV_ARGS) { - argv[argc++] = p; - while (*p && !isspace(*p) && *p != '\n') - p++; - while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */ - *p++ = '\0'; - } - - if (strcmp(argv[0], "nameserver") == 0) { - for (i = 1; i < argc && __nameservers < MAX_SERVERS; i++) { - __nameserver[__nameservers++] = strdup(argv[i]); /* TODO: what if this fails? */ - DPRINTF("adding nameserver %s\n", argv[i]); - } - } - - /* domain and search are mutually exclusive, the last one wins */ - if (strcmp(argv[0],"domain") == 0 || strcmp(argv[0],"search") == 0) { - while (__searchdomains > 0) { - free(__searchdomain[--__searchdomains]); - __searchdomain[__searchdomains] = NULL; - } - for (i = 1; i < argc && __searchdomains < MAX_SEARCH; i++) { - __searchdomain[__searchdomains++] = strdup(argv[i]); /* TODO: what if this fails? */ - DPRINTF("adding search %s\n", argv[i]); - } - } - } - fclose(fp); - DPRINTF("nameservers = %d\n", __nameservers); - goto DONE; - } - DPRINTF("failed to open %s\n", "resolv.conf"); - h_errno = NO_RECOVERY; - - /* rv = -1; */ - - DONE: - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - /* return rv; */ -} -#endif - - -#ifdef L_closenameservers - -void attribute_hidden __close_nameservers(void) -{ - __UCLIBC_MUTEX_LOCK(__resolv_lock); - while (__nameservers > 0) { - free(__nameserver[--__nameservers]); - __nameserver[__nameservers] = NULL; - } - while (__searchdomains > 0) { - free(__searchdomain[--__searchdomains]); - __searchdomain[__searchdomains] = NULL; - } - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); -} -#endif - -#ifdef L_gethostbyname - -struct hostent *gethostbyname(const char *name) -{ - static struct hostent h; - static char buf[sizeof(struct in_addr) + - sizeof(struct in_addr *)*2 + - sizeof(char *)*ALIAS_DIM + 384/*namebuffer*/ + 32/* margin */]; - struct hostent *hp; - - gethostbyname_r(name, &h, buf, sizeof(buf), &hp, &h_errno); - - return hp; -} -libc_hidden_def(gethostbyname) -#endif - -#ifdef L_gethostbyname2 - -struct hostent *gethostbyname2(const char *name, int family) -{ -#ifndef __UCLIBC_HAS_IPV6__ - return family == AF_INET ? gethostbyname(name) : (struct hostent*)0; -#else /* __UCLIBC_HAS_IPV6__ */ - static struct hostent h; - static char buf[sizeof(struct in6_addr) + - sizeof(struct in6_addr *)*2 + - sizeof(char *)*ALIAS_DIM + 384/*namebuffer*/ + 32/* margin */]; - struct hostent *hp; - - gethostbyname2_r(name, family, &h, buf, sizeof(buf), &hp, &h_errno); - - return hp; -#endif /* __UCLIBC_HAS_IPV6__ */ -} -#endif - - - -#ifdef L_res_init -/* We use __resolv_lock to guard access to global '_res' */ -struct __res_state _res; - -int res_init(void) -{ - struct __res_state *rp = &(_res); - - __UCLIBC_MUTEX_LOCK(__resolv_lock); /* must be a recursive lock! */ - __close_nameservers(); - __open_nameservers(); - rp->retrans = RES_TIMEOUT; - rp->retry = 4; - rp->options = RES_INIT; - rp->id = (u_int) random(); - rp->nsaddr.sin_addr.s_addr = INADDR_ANY; - rp->nsaddr.sin_family = AF_INET; - rp->nsaddr.sin_port = htons(NAMESERVER_PORT); - rp->ndots = 1; - /** rp->pfcode = 0; **/ - rp->_vcsock = -1; - /** rp->_flags = 0; **/ - /** rp->qhook = NULL; **/ - /** rp->rhook = NULL; **/ - /** rp->_u._ext.nsinit = 0; **/ - - if (__searchdomains) { - int i; - for (i = 0; i < __searchdomains; i++) - rp->dnsrch[i] = __searchdomain[i]; - } - - if (__nameservers) { - int i; - struct in_addr a; - for (i = 0; i < __nameservers; i++) { - if (inet_aton(__nameserver[i], &a)) { - rp->nsaddr_list[i].sin_addr = a; - rp->nsaddr_list[i].sin_family = AF_INET; - rp->nsaddr_list[i].sin_port = htons(NAMESERVER_PORT); - } - } - } - rp->nscount = __nameservers; - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - - return 0; -} -libc_hidden_def(res_init) - -#ifdef __UCLIBC_HAS_BSD_RES_CLOSE__ -void res_close(void) -{ - __close_nameservers(); - memset(&_res, 0, sizeof(_res)); -} -#endif - -#endif - - -#ifdef L_res_query - -#ifndef MIN -#define MIN(x, y) ((x) < (y) ? (x) : (y)) -#endif - -int res_query(const char *dname, int class, int type, - unsigned char *answer, int anslen) -{ - int i; - unsigned char * packet = 0; - struct resolv_answer a; - int __nameserversXX; - char ** __nameserverXX; - - __open_nameservers(); - if (!dname || class != 1 /* CLASS_IN */) { - h_errno = NO_RECOVERY; - return -1; - } - - memset(&a, '\0', sizeof(a)); - - __UCLIBC_MUTEX_LOCK(__resolv_lock); - __nameserversXX = __nameservers; - __nameserverXX = __nameserver; - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - i = __dns_lookup(dname, type, __nameserversXX, __nameserverXX, &packet, &a); - - if (i < 0) { - h_errno = TRY_AGAIN; - return -1; - } - - free(a.dotted); - - if (a.atype == type) { /* CNAME */ - i = MIN(anslen, i); - memcpy(answer, packet, i); - } - free(packet); - return i; -} -libc_hidden_def(res_query) - -/* - * Formulate a normal query, send, and retrieve answer in supplied buffer. - * Return the size of the response on success, -1 on error. - * If enabled, implement search rules until answer or unrecoverable failure - * is detected. Error code, if any, is left in h_errno. - */ -#define __TRAILING_DOT (1<<0) -#define __GOT_NODATA (1<<1) -#define __GOT_SERVFAIL (1<<2) -#define __TRIED_AS_IS (1<<3) -int res_search(const char *name, int class, int type, u_char *answer, - int anslen) -{ - const char *cp, * const *domain; - HEADER *hp = (HEADER *)(void *)answer; - u_int dots; - unsigned _state = 0; - int ret, saved_herrno; - u_long _res_options; - unsigned _res_ndots; - char **_res_dnsrch; - - __UCLIBC_MUTEX_LOCK(__resolv_lock); - _res_options = _res.options; - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - if ((!name || !answer) || ((_res_options & RES_INIT) == 0 && res_init() == -1)) { - h_errno = NETDB_INTERNAL; - return -1; - } - - errno = 0; - h_errno = HOST_NOT_FOUND; /* default, if we never query */ - dots = 0; - for (cp = name; *cp; cp++) - dots += (*cp == '.'); - - if (cp > name && *--cp == '.') - _state |= __TRAILING_DOT; - - /* - * If there are dots in the name already, let's just give it a try - * 'as is'. The threshold can be set with the "ndots" option. - */ - saved_herrno = -1; - __UCLIBC_MUTEX_LOCK(__resolv_lock); - _res_ndots = _res.ndots; - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - if (dots >= _res_ndots) { - ret = res_querydomain(name, NULL, class, type, answer, anslen); - if (ret > 0) - return ret; - saved_herrno = h_errno; - _state |= __TRIED_AS_IS; - } - - /* - * We do at least one level of search if - * - there is no dot and RES_DEFNAME is set, or - * - there is at least one dot, there is no trailing dot, - * and RES_DNSRCH is set. - */ - __UCLIBC_MUTEX_LOCK(__resolv_lock); - _res_options = _res.options; - _res_dnsrch = _res.dnsrch; - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - if ((!dots && (_res_options & RES_DEFNAMES)) || - (dots && !(_state & __TRAILING_DOT) && (_res_options & RES_DNSRCH))) { - bool done = 0; - - for (domain = (const char * const *)_res_dnsrch; - *domain && !done; - domain++) { - - ret = res_querydomain(name, *domain, class, type, - answer, anslen); - if (ret > 0) - return ret; - - /* - * If no server present, give up. - * If name isn't found in this domain, - * keep trying higher domains in the search list - * (if that's enabled). - * On a NO_DATA error, keep trying, otherwise - * a wildcard entry of another type could keep us - * from finding this entry higher in the domain. - * If we get some other error (negative answer or - * server failure), then stop searching up, - * but try the input name below in case it's - * fully-qualified. - */ - if (errno == ECONNREFUSED) { - h_errno = TRY_AGAIN; - return -1; - } - - switch (h_errno) { - case NO_DATA: - _state |= __GOT_NODATA; - /* FALLTHROUGH */ - case HOST_NOT_FOUND: - /* keep trying */ - break; - case TRY_AGAIN: - if (hp->rcode == SERVFAIL) { - /* try next search element, if any */ - _state |= __GOT_SERVFAIL; - break; - } - /* FALLTHROUGH */ - default: - /* anything else implies that we're done */ - done = 1; - } - /* - * if we got here for some reason other than DNSRCH, - * we only wanted one iteration of the loop, so stop. - */ - __UCLIBC_MUTEX_LOCK(__resolv_lock); - _res_options = _res.options; - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - if (!(_res_options & RES_DNSRCH)) - done = 1; - } - } - - /* - * if we have not already tried the name "as is", do that now. - * note that we do this regardless of how many dots were in the - * name or whether it ends with a dot. - */ - if (!(_state & __TRIED_AS_IS)) { - ret = res_querydomain(name, NULL, class, type, answer, anslen); - if (ret > 0) - return ret; - } +#ifdef L_read_etc_hosts_r - /* - * if we got here, we didn't satisfy the search. - * if we did an initial full query, return that query's h_errno - * (note that we wouldn't be here if that query had succeeded). - * else if we ever got a nodata, send that back as the reason. - * else send back meaningless h_errno, that being the one from - * the last DNSRCH we did. - */ - if (saved_herrno != -1) - h_errno = saved_herrno; - else if (_state & __GOT_NODATA) - h_errno = NO_DATA; - else if (_state & __GOT_SERVFAIL) - h_errno = TRY_AGAIN; - return -1; -} -#undef __TRAILING_DOT -#undef __GOT_NODATA -#undef __GOT_SERVFAIL -#undef __TRIED_AS_IS -/* - * Perform a call on res_query on the concatenation of name and domain, - * removing a trailing dot from name if domain is NULL. - */ -int res_querydomain(const char *name, const char *domain, int class, int type, - u_char * answer, int anslen) +parser_t * __open_etc_hosts(void) { - char nbuf[MAXDNAME]; - const char *longname = nbuf; - size_t n, d; - u_long _res_options; - - __UCLIBC_MUTEX_LOCK(__resolv_lock); - _res_options = _res.options; - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - if ((!name || !answer) || ((_res_options & RES_INIT) == 0 && res_init() == -1)) { - h_errno = NETDB_INTERNAL; - return -1; - } - -#ifdef DEBUG - __UCLIBC_MUTEX_LOCK(__resolv_lock); - _res_options = _res.options; - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - if (_res_options & RES_DEBUG) - printf(";; res_querydomain(%s, %s, %d, %d)\n", - name, (domain ? domain : "<Nil>"), class, type); + parser_t *parser; + parser = config_open("/etc/hosts"); +#ifdef FALLBACK_TO_CONFIG_RESOLVCONF + if (parser == NULL) + parser = config_open("/etc/config/hosts"); #endif - if (domain == NULL) { - /* - * Check for trailing '.'; - * copy without '.' if present. - */ - n = strlen(name); - if (n + 1 > sizeof(nbuf)) { - h_errno = NO_RECOVERY; - return -1; - } - if (n > 0 && name[--n] == '.') { - strncpy(nbuf, name, n); - nbuf[n] = '\0'; - } else - longname = name; - } else { - n = strlen(name); - d = strlen(domain); - if (n + 1 + d + 1 > sizeof(nbuf)) { - h_errno = NO_RECOVERY; - return -1; - } - snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); - } - return res_query(longname, class, type, answer, anslen); + return parser; } -libc_hidden_def(res_querydomain) - -/* res_mkquery */ -/* res_send */ -/* dn_comp */ -/* dn_expand */ -#endif -#ifdef L_gethostbyaddr -struct hostent *gethostbyaddr (const void *addr, socklen_t len, int type) +#define MINTOKENS 2 /* ip address + canonical name */ +#define MAXTOKENS (MINTOKENS + MAXALIASES) +#define HALISTOFF (sizeof(char*) * (MAXTOKENS + 1)) /* reserve space for list terminator */ +#define INADDROFF (HALISTOFF + 2 * sizeof(char*)) + +int __read_etc_hosts_r( + parser_t * parser, + const char *name, + int type, + enum etc_hosts_action action, + struct hostent *result_buf, + char *buf, size_t buflen, + struct hostent **result, + int *h_errnop) { - static struct hostent h; - static char buf[ -#ifndef __UCLIBC_HAS_IPV6__ - sizeof(struct in_addr) + sizeof(struct in_addr *)*2 + + char **tok = NULL; + struct in_addr *h_addr0 = NULL; + const size_t aliaslen = INADDROFF + +#ifdef __UCLIBC_HAS_IPV6__ + sizeof(struct in6_addr) #else - sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + -#endif /* __UCLIBC_HAS_IPV6__ */ - sizeof(char *)*ALIAS_DIM + 384 /*namebuffer*/ + 32 /* margin */]; - struct hostent *hp; - - gethostbyaddr_r(addr, len, type, &h, buf, sizeof(buf), &hp, &h_errno); - - return hp; -} -libc_hidden_def(gethostbyaddr) + sizeof(struct in_addr) #endif + ; + int ret = HOST_NOT_FOUND; + /* make sure pointer is aligned */ + int i = ALIGN_BUFFER_OFFSET(buf); + buf += i; + buflen -= i; - -#ifdef L_read_etc_hosts_r - -FILE * __open_etc_hosts(void) -{ - FILE * fp; - if ((fp = fopen("/etc/hosts", "r")) == NULL) { - fp = fopen("/etc/config/hosts", "r"); - } - return fp; -} - -int attribute_hidden __read_etc_hosts_r(FILE * fp, const char * name, int type, - enum etc_hosts_action action, - struct hostent * result_buf, - char * buf, size_t buflen, - struct hostent ** result, - int * h_errnop) -{ - struct in_addr *in = NULL; - struct in_addr **addr_list = NULL; -#ifdef __UCLIBC_HAS_IPV6__ - struct in6_addr *in6 = NULL; - struct in6_addr **addr_list6 =NULL; -#endif /* __UCLIBC_HAS_IPV6__ */ - char *cp, **alias; - int aliases, i, ret = HOST_NOT_FOUND; - - /* make sure user char * is aligned */ - i = ALIGN_BUFFER_OFFSET(buf); - if (unlikely(i)) { - if (buflen < i) - return ERANGE; - buf += i; - buflen -= i; - } - - if (buflen < sizeof(char *)*ALIAS_DIM) + *h_errnop = NETDB_INTERNAL; + if (/* (ssize_t)buflen < 0 || */ buflen < aliaslen + || (buflen - aliaslen) < BUFSZ + 1) return ERANGE; - alias = (char **)buf; - buf += sizeof(char **)*ALIAS_DIM; - buflen -= sizeof(char **)*ALIAS_DIM; - - if (action != GETHOSTENT) { -#ifdef __UCLIBC_HAS_IPV6__ - char *p = buf; - size_t len = buflen; -#endif /* __UCLIBC_HAS_IPV6__ */ - *h_errnop = NETDB_INTERNAL; - if (buflen < sizeof(*in)) - return ERANGE; - in = (struct in_addr*)buf; - buf += sizeof(*in); - buflen -= sizeof(*in); - - if (buflen < sizeof(*addr_list)*2) - return ERANGE; - addr_list = (struct in_addr **)buf; - buf += sizeof(*addr_list)*2; - buflen -= sizeof(*addr_list)*2; - -#ifdef __UCLIBC_HAS_IPV6__ - if (len < sizeof(*in6)) - return ERANGE; - in6 = (struct in6_addr*)p; - p += sizeof(*in6); - len -= sizeof(*in6); - - if (len < sizeof(*addr_list6)*2) - return ERANGE; - addr_list6 = (struct in6_addr**)p; - p += sizeof(*addr_list6)*2; - len -= sizeof(*addr_list6)*2; - - if (len < buflen) { - buflen = len; - buf = p; - } -#endif /* __UCLIBC_HAS_IPV6__ */ - - if (buflen < 80) - return ERANGE; - - fp = __open_etc_hosts(); - if (fp == NULL) { - result = NULL; - return errno; - } + if (parser == NULL) + parser = __open_etc_hosts(); + if (parser == NULL) { + *result = NULL; + return errno; } - + /* Layout in buf: + * char *alias[MAXTOKENS] = {address, name, aliases...} + * char **h_addr_list[1] = {*in[6]_addr, NULL} + * struct in[6]_addr + * char line_buffer[BUFSZ+]; + */ + parser->data = buf; + parser->data_len = aliaslen; + parser->line_len = buflen - aliaslen; *h_errnop = HOST_NOT_FOUND; - while (fgets(buf, buflen, fp)) { - if ((cp = strchr(buf, '#'))) - *cp = '\0'; - DPRINTF("Looking at: %s\n", buf); - aliases = 0; - - cp = buf; - while (*cp) { - while (*cp && isspace(*cp)) - *cp++ = '\0'; - if (!*cp) - continue; - if (aliases < (2+MAX_ALIASES)) - alias[aliases++] = cp; - while (*cp && !isspace(*cp)) - cp++; - } - alias[aliases] = 0; - - if (aliases < 2) - continue; /* syntax error really */ - + /* <ip>[[:space:]][<aliases>] */ + while (config_read(parser, &tok, MAXTOKENS, MINTOKENS, "# \t", PARSE_NORMAL)) { + result_buf->h_aliases = tok+1; if (action == GETHOSTENT) { /* Return whatever the next entry happens to be. */ - break; + ; } else if (action == GET_HOSTS_BYADDR) { - if (strcmp(name, alias[0]) != 0) - continue; - } else { - /* GET_HOSTS_BYNAME */ - for (i = 1; i < aliases; i++) - if (strcasecmp(name, alias[i]) == 0) - break; - if (i >= aliases) + if (strcmp(name, *tok) != 0) continue; + } else { /* GET_HOSTS_BYNAME */ + int aliases = 0; + char **alias = tok + 1; + while (aliases < MAXALIASES) { + char *tmp = *(alias+aliases++); + if (tmp && strcasecmp(name, tmp) == 0) + goto found; + } + continue; } - - if (type == AF_INET && inet_pton(AF_INET, alias[0], in) > 0) { +found: + result_buf->h_name = *(result_buf->h_aliases++); + result_buf->h_addr_list = (char**)(buf + HALISTOFF); + *(result_buf->h_addr_list + 1) = '\0'; + h_addr0 = (struct in_addr*)(buf + INADDROFF); + result_buf->h_addr = (char*)h_addr0; + if (0) /* nothing */; +#ifdef __UCLIBC_HAS_IPV4__ + else if (type == AF_INET + && inet_pton(AF_INET, *tok, h_addr0) > 0) { DPRINTF("Found INET\n"); - addr_list[0] = in; - addr_list[1] = 0; - result_buf->h_name = alias[1]; result_buf->h_addrtype = AF_INET; - result_buf->h_length = sizeof(*in); - result_buf->h_addr_list = (char**) addr_list; - result_buf->h_aliases = alias + 2; + result_buf->h_length = sizeof(struct in_addr); *result = result_buf; ret = NETDB_SUCCESS; + } +#endif #ifdef __UCLIBC_HAS_IPV6__ - } else if (type == AF_INET6 && inet_pton(AF_INET6, alias[0], in6) > 0) { +#define in6 ((struct in6_addr *)buf) + else if (type == AF_INET6 + && inet_pton(AF_INET6, *tok, h_addr0) > 0) { DPRINTF("Found INET6\n"); - addr_list6[0] = in6; - addr_list6[1] = 0; - result_buf->h_name = alias[1]; result_buf->h_addrtype = AF_INET6; - result_buf->h_length = sizeof(*in6); - result_buf->h_addr_list = (char**) addr_list6; - result_buf->h_aliases = alias + 2; + result_buf->h_length = sizeof(struct in6_addr); *result = result_buf; ret = NETDB_SUCCESS; -#endif /* __UCLIBC_HAS_IPV6__ */ - } else { + } +#endif + else { /* continue parsing in the hope the user has multiple * host types listed in the database like so: * <ipv4 addr> host * <ipv6 addr> host * If looking for an IPv6 addr, don't bail when we got the IPv4 */ - DPRINTF("Error: Found host but diff network type\n"); + DPRINTF("Error: Found host but different address family\n"); + /* NB: gethostbyname2_r depends on this feature + * to avoid looking for IPv6 addr of "localhost" etc */ ret = TRY_AGAIN; continue; } - - if (action != GETHOSTENT) - fclose(fp); - return ret; + break; } if (action != GETHOSTENT) - fclose(fp); + config_close(parser); return ret; +#undef in6 } -#endif - - -#ifdef L_gethostent -__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); +#endif /* L_read_etc_hosts_r */ -static smallint __stay_open; -static FILE * __gethostent_fp; - -void endhostent(void) -{ - __UCLIBC_MUTEX_LOCK(mylock); - __stay_open = 0; - if (__gethostent_fp) { - fclose(__gethostent_fp); - __gethostent_fp = NULL; - } - __UCLIBC_MUTEX_UNLOCK(mylock); -} - -void sethostent(int stay_open) -{ - __UCLIBC_MUTEX_LOCK(mylock); - __stay_open = (stay_open != 0); - __UCLIBC_MUTEX_UNLOCK(mylock); -} - -int gethostent_r(struct hostent *result_buf, char *buf, size_t buflen, - struct hostent **result, int *h_errnop) -{ - int ret; - - __UCLIBC_MUTEX_LOCK(mylock); - if (__gethostent_fp == NULL) { - __gethostent_fp = __open_etc_hosts(); - if (__gethostent_fp == NULL) { - *result = NULL; - ret = TRY_AGAIN; - goto DONE; - } - } - - ret = __read_etc_hosts_r(__gethostent_fp, NULL, AF_INET, GETHOSTENT, - result_buf, buf, buflen, result, h_errnop); - if (__stay_open == 0) { - fclose(__gethostent_fp); - __gethostent_fp = NULL; - } -DONE: - __UCLIBC_MUTEX_UNLOCK(mylock); - return ret; -} -libc_hidden_def(gethostent_r) - -struct hostent *gethostent(void) -{ - static struct hostent h; - static char buf[ -#ifndef __UCLIBC_HAS_IPV6__ - sizeof(struct in_addr) + sizeof(struct in_addr *)*2 + -#else - sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + -#endif /* __UCLIBC_HAS_IPV6__ */ - sizeof(char *)*ALIAS_DIM + - 80 /*namebuffer*/ + 2 /* margin */]; - struct hostent *host; - - __UCLIBC_MUTEX_LOCK(mylock); - gethostent_r(&h, buf, sizeof(buf), &host, &h_errno); - __UCLIBC_MUTEX_UNLOCK(mylock); - return host; -} -#endif #ifdef L_get_hosts_byname_r -int attribute_hidden __get_hosts_byname_r(const char * name, int type, - struct hostent * result_buf, - char * buf, size_t buflen, - struct hostent ** result, - int * h_errnop) +int __get_hosts_byname_r(const char *name, + int type, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) { return __read_etc_hosts_r(NULL, name, type, GET_HOSTS_BYNAME, result_buf, buf, buflen, result, h_errnop); } -#endif +#endif /* L_get_hosts_byname_r */ + #ifdef L_get_hosts_byaddr_r -int attribute_hidden __get_hosts_byaddr_r(const char * addr, int len, int type, - struct hostent * result_buf, - char * buf, size_t buflen, - struct hostent ** result, - int * h_errnop) +int __get_hosts_byaddr_r(const char *addr, + int len, + int type, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) { #ifndef __UCLIBC_HAS_IPV6__ char ipaddr[INET_ADDRSTRLEN]; #else char ipaddr[INET6_ADDRSTRLEN]; -#endif /* __UCLIBC_HAS_IPV6__ */ +#endif switch (type) { +#ifdef __UCLIBC_HAS_IPV4__ case AF_INET: if (len != sizeof(struct in_addr)) return 0; break; +#endif #ifdef __UCLIBC_HAS_IPV6__ case AF_INET6: if (len != sizeof(struct in6_addr)) return 0; break; -#endif /* __UCLIBC_HAS_IPV6__ */ +#endif default: return 0; } @@ -1819,156 +1776,152 @@ int attribute_hidden __get_hosts_byaddr_r(const char * addr, int len, int type, inet_ntop(type, addr, ipaddr, sizeof(ipaddr)); return __read_etc_hosts_r(NULL, ipaddr, type, GET_HOSTS_BYADDR, - result_buf, buf, buflen, result, h_errnop); + result_buf, buf, buflen, result, h_errnop); } -#endif +#endif /* L_get_hosts_byaddr_r */ -#ifdef L_getnameinfo -#ifndef min -# define min(x,y) (((x) > (y)) ? (y) : (x)) -#endif /* min */ +#ifdef L_getnameinfo -libc_hidden_proto(getnameinfo) -int getnameinfo(const struct sockaddr *sa, socklen_t addrlen, char *host, - socklen_t hostlen, char *serv, socklen_t servlen, - unsigned int flags) +int getnameinfo(const struct sockaddr *sa, + socklen_t addrlen, + char *host, + socklen_t hostlen, + char *serv, + socklen_t servlen, + unsigned flags) { int serrno = errno; - unsigned ok; - struct hostent *h = NULL; + bool ok = 0; + struct hostent *hoste = NULL; char domain[256]; if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM)) return EAI_BADFLAGS; - if (sa == NULL || addrlen < sizeof (sa_family_t)) - goto BAD_FAM; + if (sa == NULL || addrlen < sizeof(sa_family_t)) + return EAI_FAMILY; - ok = sa->sa_family; - if (ok == AF_LOCAL) /* valid */; + if (sa->sa_family == AF_LOCAL) /* valid */; #ifdef __UCLIBC_HAS_IPV4__ - else if (ok == AF_INET) { - if (addrlen < sizeof (struct sockaddr_in)) - goto BAD_FAM; + else if (sa->sa_family == AF_INET) { + if (addrlen < sizeof(struct sockaddr_in)) + return EAI_FAMILY; } #endif #ifdef __UCLIBC_HAS_IPV6__ - else if (ok == AF_INET6) { - if (addrlen < sizeof (struct sockaddr_in6)) - goto BAD_FAM; + else if (sa->sa_family == AF_INET6) { + if (addrlen < sizeof(struct sockaddr_in6)) + return EAI_FAMILY; } -#endif /* __UCLIBC_HAS_IPV6__ */ +#endif else -BAD_FAM: return EAI_FAMILY; - ok = 0; if (host != NULL && hostlen > 0) switch (sa->sa_family) { case AF_INET: #ifdef __UCLIBC_HAS_IPV6__ case AF_INET6: -#endif /* __UCLIBC_HAS_IPV6__ */ +#endif if (!(flags & NI_NUMERICHOST)) { + if (0) /* nothing */; #ifdef __UCLIBC_HAS_IPV6__ - if (sa->sa_family == AF_INET6) - h = gethostbyaddr ((const void *) + else if (sa->sa_family == AF_INET6) + hoste = gethostbyaddr((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr), sizeof(struct in6_addr), AF_INET6); -#endif /* __UCLIBC_HAS_IPV6__ */ -#if defined __UCLIBC_HAS_IPV6__ && defined __UCLIBC_HAS_IPV4__ - else #endif #ifdef __UCLIBC_HAS_IPV4__ - h = gethostbyaddr ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr), - sizeof(struct in_addr), AF_INET); -#endif /* __UCLIBC_HAS_IPV4__ */ + else + hoste = gethostbyaddr((const void *) + &(((const struct sockaddr_in *)sa)->sin_addr), + sizeof(struct in_addr), AF_INET); +#endif - if (h) { + if (hoste) { char *c; if ((flags & NI_NOFQDN) - && (__libc_getdomainname (domain, sizeof(domain)) == 0) - && (c = strstr (h->h_name, domain)) - && (c != h->h_name) && (*(--c) == '.')) { - strncpy (host, h->h_name, - min(hostlen, (size_t) (c - h->h_name))); - host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0'; - ok = 1; + && (getdomainname(domain, sizeof(domain)) == 0) + && (c = strstr(hoste->h_name, domain)) != NULL + && (c != hoste->h_name) && (*(--c) == '.') + ) { + strncpy(host, hoste->h_name, + MIN(hostlen, (size_t) (c - hoste->h_name))); + host[MIN(hostlen - 1, (size_t) (c - hoste->h_name))] = '\0'; } else { - strncpy (host, h->h_name, hostlen); - ok = 1; + strncpy(host, hoste->h_name, hostlen); } - } + ok = 1; + } } if (!ok) { + const char *c = NULL; + if (flags & NI_NAMEREQD) { errno = serrno; return EAI_NONAME; - } else { - const char *c; + } + if (0) /* nothing */; #ifdef __UCLIBC_HAS_IPV6__ - if (sa->sa_family == AF_INET6) { - const struct sockaddr_in6 *sin6p; + else if (sa->sa_family == AF_INET6) { + const struct sockaddr_in6 *sin6p; - sin6p = (const struct sockaddr_in6 *) sa; - - c = inet_ntop (AF_INET6, - (const void *) &sin6p->sin6_addr, host, hostlen); + sin6p = (const struct sockaddr_in6 *) sa; + c = inet_ntop(AF_INET6, + (const void *) &sin6p->sin6_addr, + host, hostlen); #if 0 - /* Does scope id need to be supported? */ - uint32_t scopeid; - scopeid = sin6p->sin6_scope_id; - if (scopeid != 0) { - /* Buffer is >= IFNAMSIZ+1. */ - char scopebuf[IFNAMSIZ + 1]; - char *scopeptr; - int ni_numericscope = 0; - size_t real_hostlen = strnlen (host, hostlen); - size_t scopelen = 0; - - scopebuf[0] = SCOPE_DELIMITER; - scopebuf[1] = '\0'; - scopeptr = &scopebuf[1]; - - if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr) - || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) { - if (if_indextoname (scopeid, scopeptr) == NULL) - ++ni_numericscope; - else - scopelen = strlen (scopebuf); - } else { + /* Does scope id need to be supported? */ + uint32_t scopeid; + scopeid = sin6p->sin6_scope_id; + if (scopeid != 0) { + /* Buffer is >= IFNAMSIZ+1. */ + char scopebuf[IFNAMSIZ + 1]; + char *scopeptr; + int ni_numericscope = 0; + size_t real_hostlen = strnlen(host, hostlen); + size_t scopelen = 0; + + scopebuf[0] = SCOPE_DELIMITER; + scopebuf[1] = '\0'; + scopeptr = &scopebuf[1]; + + if (IN6_IS_ADDR_LINKLOCAL(&sin6p->sin6_addr) + || IN6_IS_ADDR_MC_LINKLOCAL(&sin6p->sin6_addr)) { + if (if_indextoname(scopeid, scopeptr) == NULL) ++ni_numericscope; - } - - if (ni_numericscope) - scopelen = 1 + snprintf (scopeptr, - (scopebuf - + sizeof scopebuf - - scopeptr), - "%u", scopeid); - - if (real_hostlen + scopelen + 1 > hostlen) - return EAI_SYSTEM; - memcpy (host + real_hostlen, scopebuf, scopelen + 1); + else + scopelen = strlen(scopebuf); + } else { + ++ni_numericscope; } -#endif + + if (ni_numericscope) + scopelen = 1 + snprintf(scopeptr, + (scopebuf + + sizeof scopebuf + - scopeptr), + "%u", scopeid); + + if (real_hostlen + scopelen + 1 > hostlen) + return EAI_SYSTEM; + memcpy(host + real_hostlen, scopebuf, scopelen + 1); } +#endif + } #endif /* __UCLIBC_HAS_IPV6__ */ -#if defined __UCLIBC_HAS_IPV6__ && defined __UCLIBC_HAS_IPV4__ - else -#endif /* __UCLIBC_HAS_IPV6__ && defined __UCLIBC_HAS_IPV4__ */ #if defined __UCLIBC_HAS_IPV4__ - c = inet_ntop (AF_INET, (const void *) - &(((const struct sockaddr_in *) sa)->sin_addr), - host, hostlen); -#endif /* __UCLIBC_HAS_IPV4__ */ - - if (c == NULL) { - errno = serrno; - return EAI_SYSTEM; - } + else { + c = inet_ntop(AF_INET, (const void *) + &(((const struct sockaddr_in *) sa)->sin_addr), + host, hostlen); + } +#endif + if (c == NULL) { + errno = serrno; + return EAI_SYSTEM; } ok = 1; } @@ -1978,8 +1931,8 @@ BAD_FAM: if (!(flags & NI_NUMERICHOST)) { struct utsname utsname; - if (!uname (&utsname)) { - strncpy (host, utsname.nodename, hostlen); + if (!uname(&utsname)) { + strncpy(host, utsname.nodename, hostlen); break; }; }; @@ -1989,29 +1942,29 @@ BAD_FAM: return EAI_NONAME; } - strncpy (host, "localhost", hostlen); + strncpy(host, "localhost", hostlen); break; - -/*Already checked above default: +/* Already checked above + default: return EAI_FAMILY; */ } if (serv && (servlen > 0)) { if (sa->sa_family == AF_LOCAL) { - strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen); + strncpy(serv, ((const struct sockaddr_un *) sa)->sun_path, servlen); } else { /* AF_INET || AF_INET6 */ if (!(flags & NI_NUMERICSERV)) { struct servent *s; - s = getservbyport (((const struct sockaddr_in *) sa)->sin_port, + s = getservbyport(((const struct sockaddr_in *) sa)->sin_port, ((flags & NI_DGRAM) ? "udp" : "tcp")); if (s) { - strncpy (serv, s->s_name, servlen); + strncpy(serv, s->s_name, servlen); goto DONE; } } - snprintf (serv, servlen, "%d", - ntohs (((const struct sockaddr_in *) sa)->sin_port)); + snprintf(serv, servlen, "%d", + ntohs(((const struct sockaddr_in *) sa)->sin_port)); } } DONE: @@ -2023,41 +1976,69 @@ DONE: return 0; } libc_hidden_def(getnameinfo) -#endif +#endif /* L_getnameinfo */ #ifdef L_gethostbyname_r -int gethostbyname_r(const char * name, - struct hostent * result_buf, - char * buf, size_t buflen, - struct hostent ** result, - int * h_errnop) +/* Bug 671 says: + * "uClibc resolver's gethostbyname does not return the requested name + * as an alias, but instead returns the canonical name. glibc's + * gethostbyname has a similar bug where it returns the requested name + * with the search domain name appended (to make a FQDN) as an alias, + * but not the original name itself. Both contradict POSIX, which says + * that the name argument passed to gethostbyname must be in the alias list" + * This is fixed now, and we differ from glibc: + * + * $ ./gethostbyname_uclibc wer.google.com + * h_name:'c13-ss-2-lb.cnet.com' + * h_length:4 + * h_addrtype:2 AF_INET + * alias:'wer.google.com' <=== + * addr: 0x4174efd8 '216.239.116.65' + * + * $ ./gethostbyname_glibc wer.google.com + * h_name:'c13-ss-2-lb.cnet.com' + * h_length:4 + * h_addrtype:2 AF_INET + * alias:'wer.google.com.com' <=== + * addr:'216.239.116.65' + * + * When examples were run, /etc/resolv.conf contained "search com" line. + */ +int gethostbyname_r(const char *name, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) { - struct in_addr *in; struct in_addr **addr_list; char **alias; + char *alias0; unsigned char *packet; struct resolv_answer a; int i; - int __nameserversXX; - char ** __nameserverXX; + int packet_len; + int wrong_af = 0; - __open_nameservers(); *result = NULL; if (!name) return EINVAL; /* do /etc/hosts first */ { - int old_errno = errno; /* Save the old errno and reset errno */ - __set_errno(0); /* to check for missing /etc/hosts. */ - - if ((i = __get_hosts_byname_r(name, AF_INET, result_buf, - buf, buflen, result, h_errnop)) == 0) + int old_errno = errno; /* save the old errno and reset errno */ + __set_errno(0); /* to check for missing /etc/hosts. */ + i = __get_hosts_byname_r(name, AF_INET, result_buf, + buf, buflen, result, h_errnop); + if (i == NETDB_SUCCESS) { + __set_errno(old_errno); return i; + } switch (*h_errnop) { case HOST_NOT_FOUND: + wrong_af = (i == TRY_AGAIN); case NO_ADDRESS: break; case NETDB_INTERNAL: @@ -2073,161 +2054,192 @@ int gethostbyname_r(const char * name, DPRINTF("Nothing found in /etc/hosts\n"); - /* make sure user char * is aligned */ - i = ALIGN_BUFFER_OFFSET(buf); - if (unlikely(i)) { - if (buflen < i) - return ERANGE; - buf += i; - buflen -= i; - } - *h_errnop = NETDB_INTERNAL; - if (buflen < sizeof(*in)) - return ERANGE; - in = (struct in_addr*)buf; - buf += sizeof(*in); - buflen -= sizeof(*in); - - if (buflen < sizeof(*addr_list)*2) - return ERANGE; - addr_list = (struct in_addr**)buf; - buf += sizeof(*addr_list)*2; - buflen -= sizeof(*addr_list)*2; - addr_list[0] = in; - addr_list[1] = 0; - - if (buflen < sizeof(char *)*ALIAS_DIM) + /* prepare future h_aliases[0] */ + i = strlen(name) + 1; + if ((ssize_t)buflen <= i) return ERANGE; + memcpy(buf, name, i); /* paranoia: name might change */ + alias0 = buf; + buf += i; + buflen -= i; + /* make sure pointer is aligned */ + i = ALIGN_BUFFER_OFFSET(buf); + buf += i; + buflen -= i; + /* Layout in buf: + * char *alias[2]; + * struct in_addr* addr_list[NN+1]; + * struct in_addr* in[NN]; + */ alias = (char **)buf; - buf += sizeof(char **)*ALIAS_DIM; - buflen -= sizeof(char **)*ALIAS_DIM; - - if (buflen < 256) + buf += sizeof(alias[0]) * 2; + buflen -= sizeof(alias[0]) * 2; + addr_list = (struct in_addr **)buf; + /* buflen may be < 0, must do signed compare */ + if ((ssize_t)buflen < 256) return ERANGE; - strncpy(buf, name, buflen); - alias[0] = buf; + /* we store only one "alias" - the name itself */ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO -- generate the full list +#endif + alias[0] = alias0; alias[1] = NULL; - /* First check if this is already an address */ - if (inet_aton(name, in)) { - result_buf->h_name = buf; - result_buf->h_addrtype = AF_INET; - result_buf->h_length = sizeof(*in); - result_buf->h_addr_list = (char **) addr_list; - result_buf->h_aliases = alias; - *result = result_buf; - *h_errnop = NETDB_SUCCESS; - return NETDB_SUCCESS; + /* maybe it is already an address? */ + { + struct in_addr *in = (struct in_addr *)(buf + sizeof(addr_list[0]) * 2); + if (inet_aton(name, in)) { + addr_list[0] = in; + addr_list[1] = NULL; + result_buf->h_name = alias0; + result_buf->h_aliases = alias; + result_buf->h_addrtype = AF_INET; + result_buf->h_length = sizeof(struct in_addr); + result_buf->h_addr_list = (char **) addr_list; + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + return NETDB_SUCCESS; + } } - for (;;) { - __UCLIBC_MUTEX_LOCK(__resolv_lock); - __nameserversXX = __nameservers; - __nameserverXX = __nameserver; - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - a.buf = buf; - a.buflen = buflen; - a.add_count = 0; - i = __dns_lookup(name, T_A, __nameserversXX, __nameserverXX, &packet, &a); + /* what if /etc/hosts has it but it's not IPv4? + * F.e. "::1 localhost6". We don't do DNS query for such hosts - + * "ping localhost6" should be fast even if DNS server is down! */ + if (wrong_af) { + *h_errnop = HOST_NOT_FOUND; + return TRY_AGAIN; + } - if (i < 0) { - *h_errnop = HOST_NOT_FOUND; - DPRINTF("__dns_lookup\n"); - return TRY_AGAIN; - } + /* talk to DNS servers */ + a.buf = buf; + /* take into account that at least one address will be there, + * we'll need space for one in_addr + two addr_list[] elems */ + a.buflen = buflen - ((sizeof(addr_list[0]) * 2 + sizeof(struct in_addr))); + a.add_count = 0; + packet_len = __dns_lookup(name, T_A, &packet, &a); + if (packet_len < 0) { + *h_errnop = HOST_NOT_FOUND; + DPRINTF("__dns_lookup returned < 0\n"); + return TRY_AGAIN; + } - if ((a.rdlength + sizeof(struct in_addr*)) * a.add_count + 256 > buflen) { - free(a.dotted); - free(packet); - *h_errnop = NETDB_INTERNAL; + if (a.atype == T_A) { /* ADDRESS */ + /* we need space for addr_list[] and one IPv4 address */ + /* + 1 accounting for 1st addr (it's in a.rdata), + * another + 1 for NULL in last addr_list[]: */ + int need_bytes = sizeof(addr_list[0]) * (a.add_count + 1 + 1) + /* for 1st addr (it's in a.rdata): */ + + sizeof(struct in_addr); + /* how many bytes will 2nd and following addresses take? */ + int ips_len = a.add_count * a.rdlength; + + buflen -= (need_bytes + ips_len); + if ((ssize_t)buflen < 0) { DPRINTF("buffer too small for all addresses\n"); - return ERANGE; - } else if (a.add_count > 0) { - memmove(buf - sizeof(struct in_addr*)*2, buf, a.add_count * a.rdlength); - addr_list = (struct in_addr**)(buf + a.add_count * a.rdlength); - addr_list[0] = in; - for (i = a.add_count - 1; i >= 0; --i) - addr_list[i+1] = (struct in_addr*)(buf - sizeof(struct in_addr*)*2 + a.rdlength * i); - addr_list[a.add_count + 1] = 0; - buflen -= (((char*)&(addr_list[a.add_count + 2])) - buf); - buf = (char*)&addr_list[a.add_count + 2]; + /* *h_errnop = NETDB_INTERNAL; - already is */ + i = ERANGE; + goto free_and_ret; } - strncpy(buf, a.dotted, buflen); - free(a.dotted); + /* if there are additional addresses in buf, + * move them forward so that they are not destroyed */ + DPRINTF("a.add_count:%d a.rdlength:%d a.rdata:%p\n", a.add_count, a.rdlength, a.rdata); + memmove(buf + need_bytes, buf, ips_len); - if (a.atype == T_A) { /* ADDRESS */ - memcpy(in, a.rdata, sizeof(*in)); - result_buf->h_name = buf; - result_buf->h_addrtype = AF_INET; - result_buf->h_length = sizeof(*in); - result_buf->h_addr_list = (char **) addr_list; -#ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO -- generate the full list -#endif - result_buf->h_aliases = alias; /* TODO: generate the full list */ - free(packet); - break; - } else { - free(packet); - *h_errnop = HOST_NOT_FOUND; - return TRY_AGAIN; + /* 1st address is in a.rdata, insert it */ + buf += need_bytes - sizeof(struct in_addr); + memcpy(buf, a.rdata, sizeof(struct in_addr)); + + /* fill addr_list[] */ + for (i = 0; i <= a.add_count; i++) { + addr_list[i] = (struct in_addr*)buf; + buf += sizeof(struct in_addr); + } + addr_list[i] = NULL; + + /* if we have enough space, we can report "better" name + * (it may contain search domains attached by __dns_lookup, + * or CNAME of the host if it is different from the name + * we used to find it) */ + if (a.dotted && buflen > strlen(a.dotted)) { + strcpy(buf, a.dotted); + alias0 = buf; } + + result_buf->h_name = alias0; + result_buf->h_aliases = alias; + result_buf->h_addrtype = AF_INET; + result_buf->h_length = sizeof(struct in_addr); + result_buf->h_addr_list = (char **) addr_list; + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + i = NETDB_SUCCESS; + goto free_and_ret; } - *result = result_buf; - *h_errnop = NETDB_SUCCESS; - return NETDB_SUCCESS; + *h_errnop = HOST_NOT_FOUND; + __set_h_errno(HOST_NOT_FOUND); + i = TRY_AGAIN; + + free_and_ret: + free(a.dotted); + free(packet); + return i; } libc_hidden_def(gethostbyname_r) -#endif +#endif /* L_gethostbyname_r */ + #ifdef L_gethostbyname2_r -int gethostbyname2_r(const char *name, int family, - struct hostent * result_buf, - char * buf, size_t buflen, - struct hostent ** result, - int * h_errnop) +int gethostbyname2_r(const char *name, + int family, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) { #ifndef __UCLIBC_HAS_IPV6__ return family == (AF_INET) ? gethostbyname_r(name, result_buf, buf, buflen, result, h_errnop) : HOST_NOT_FOUND; -#else /* __UCLIBC_HAS_IPV6__ */ - struct in6_addr *in; +#else struct in6_addr **addr_list; + char **alias; + char *alias0; unsigned char *packet; struct resolv_answer a; int i; - int nest = 0; - int __nameserversXX; - char ** __nameserverXX; + int packet_len; + int wrong_af = 0; if (family == AF_INET) return gethostbyname_r(name, result_buf, buf, buflen, result, h_errnop); + *result = NULL; if (family != AF_INET6) return EINVAL; - __open_nameservers(); - *result = NULL; if (!name) return EINVAL; /* do /etc/hosts first */ { - int old_errno = errno; /* Save the old errno and reset errno */ - __set_errno(0); /* to check for missing /etc/hosts. */ - - if ((i = __get_hosts_byname_r(name, family, result_buf, - buf, buflen, result, h_errnop)) == 0) + int old_errno = errno; /* save the old errno and reset errno */ + __set_errno(0); /* to check for missing /etc/hosts. */ + i = __get_hosts_byname_r(name, AF_INET6 /*family*/, result_buf, + buf, buflen, result, h_errnop); + if (i == NETDB_SUCCESS) { + __set_errno(old_errno); return i; + } switch (*h_errnop) { case HOST_NOT_FOUND: + wrong_af = (i == TRY_AGAIN); case NO_ADDRESS: break; case NETDB_INTERNAL: @@ -2244,139 +2256,189 @@ int gethostbyname2_r(const char *name, int family, DPRINTF("Nothing found in /etc/hosts\n"); *h_errnop = NETDB_INTERNAL; - if (buflen < sizeof(*in)) - return ERANGE; - in = (struct in6_addr*)buf; - buf += sizeof(*in); - buflen -= sizeof(*in); - if (buflen < sizeof(*addr_list)*2) + /* prepare future h_aliases[0] */ + i = strlen(name) + 1; + if ((ssize_t)buflen <= i) return ERANGE; - addr_list = (struct in6_addr**)buf; - buf += sizeof(*addr_list)*2; - buflen -= sizeof(*addr_list)*2; - - addr_list[0] = in; - addr_list[1] = 0; - - if (buflen < 256) + memcpy(buf, name, i); /* paranoia: name might change */ + alias0 = buf; + buf += i; + buflen -= i; + /* make sure pointer is aligned */ + i = ALIGN_BUFFER_OFFSET(buf); + buf += i; + buflen -= i; + /* Layout in buf: + * char *alias[2]; + * struct in6_addr* addr_list[NN+1]; + * struct in6_addr* in[NN]; + */ + alias = (char **)buf; + buf += sizeof(alias[0]) * 2; + buflen -= sizeof(alias[0]) * 2; + addr_list = (struct in6_addr **)buf; + /* buflen may be < 0, must do signed compare */ + if ((ssize_t)buflen < 256) return ERANGE; - strncpy(buf, name, buflen); - /* First check if this is already an address */ - if (inet_pton(AF_INET6, name, in)) { - result_buf->h_name = buf; - result_buf->h_addrtype = AF_INET6; - result_buf->h_length = sizeof(*in); - result_buf->h_addr_list = (char **) addr_list; - *result = result_buf; - *h_errnop = NETDB_SUCCESS; - return NETDB_SUCCESS; - } + /* we store only one "alias" - the name itself */ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO -- generate the full list +#endif + alias[0] = alias0; + alias[1] = NULL; - memset((char *) &a, '\0', sizeof(a)); + /* maybe it is already an address? */ + { + struct in6_addr *in = (struct in6_addr *)(buf + sizeof(addr_list[0]) * 2); + if (inet_pton(AF_INET6, name, in)) { + addr_list[0] = in; + addr_list[1] = NULL; + result_buf->h_name = alias0; + result_buf->h_aliases = alias; + result_buf->h_addrtype = AF_INET6; + result_buf->h_length = sizeof(struct in6_addr); + result_buf->h_addr_list = (char **) addr_list; + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + return NETDB_SUCCESS; + } + } - for (;;) { - __UCLIBC_MUTEX_LOCK(__resolv_lock); - __nameserversXX = __nameservers; - __nameserverXX = __nameserver; - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + /* what if /etc/hosts has it but it's not IPv6? + * F.e. "127.0.0.1 localhost". We don't do DNS query for such hosts - + * "ping localhost" should be fast even if DNS server is down! */ + if (wrong_af) { + *h_errnop = HOST_NOT_FOUND; + return TRY_AGAIN; + } - i = __dns_lookup(buf, T_AAAA, __nameserversXX, __nameserverXX, &packet, &a); + /* talk to DNS servers */ + a.buf = buf; + /* take into account that at least one address will be there, + * we'll need space of one in6_addr + two addr_list[] elems */ + a.buflen = buflen - ((sizeof(addr_list[0]) * 2 + sizeof(struct in6_addr))); + a.add_count = 0; + packet_len = __dns_lookup(name, T_AAAA, &packet, &a); + if (packet_len < 0) { + *h_errnop = HOST_NOT_FOUND; + DPRINTF("__dns_lookup returned < 0\n"); + return TRY_AGAIN; + } - if (i < 0) { - *h_errnop = HOST_NOT_FOUND; - return TRY_AGAIN; + if (a.atype == T_AAAA) { /* ADDRESS */ + /* we need space for addr_list[] and one IPv6 address */ + /* + 1 accounting for 1st addr (it's in a.rdata), + * another + 1 for NULL in last addr_list[]: */ + int need_bytes = sizeof(addr_list[0]) * (a.add_count + 1 + 1) + /* for 1st addr (it's in a.rdata): */ + + sizeof(struct in6_addr); + /* how many bytes will 2nd and following addresses take? */ + int ips_len = a.add_count * a.rdlength; + + buflen -= (need_bytes + ips_len); + if ((ssize_t)buflen < 0) { + DPRINTF("buffer too small for all addresses\n"); + /* *h_errnop = NETDB_INTERNAL; - already is */ + i = ERANGE; + goto free_and_ret; } - strncpy(buf, a.dotted, buflen); - free(a.dotted); + /* if there are additional addresses in buf, + * move them forward so that they are not destroyed */ + DPRINTF("a.add_count:%d a.rdlength:%d a.rdata:%p\n", a.add_count, a.rdlength, a.rdata); + memmove(buf + need_bytes, buf, ips_len); - if (a.atype == T_CNAME) { /* CNAME */ - DPRINTF("Got a CNAME in gethostbyname()\n"); - i = __decode_dotted(packet, a.rdoffset, buf, buflen); - free(packet); + /* 1st address is in a.rdata, insert it */ + buf += need_bytes - sizeof(struct in6_addr); + memcpy(buf, a.rdata, sizeof(struct in6_addr)); - if (i < 0) { - *h_errnop = NO_RECOVERY; - return -1; - } - if (++nest > MAX_RECURSE) { - *h_errnop = NO_RECOVERY; - return -1; - } - continue; - } else if (a.atype == T_AAAA) { /* ADDRESS */ - memcpy(in, a.rdata, sizeof(*in)); - result_buf->h_name = buf; - result_buf->h_addrtype = AF_INET6; - result_buf->h_length = sizeof(*in); - result_buf->h_addr_list = (char **) addr_list; - free(packet); - break; - } else { - free(packet); - *h_errnop = HOST_NOT_FOUND; - return TRY_AGAIN; + /* fill addr_list[] */ + for (i = 0; i <= a.add_count; i++) { + addr_list[i] = (struct in6_addr*)buf; + buf += sizeof(struct in6_addr); } + addr_list[i] = NULL; + + /* if we have enough space, we can report "better" name + * (it may contain search domains attached by __dns_lookup, + * or CNAME of the host if it is different from the name + * we used to find it) */ + if (a.dotted && buflen > strlen(a.dotted)) { + strcpy(buf, a.dotted); + alias0 = buf; + } + + result_buf->h_name = alias0; + result_buf->h_aliases = alias; + result_buf->h_addrtype = AF_INET6; + result_buf->h_length = sizeof(struct in6_addr); + result_buf->h_addr_list = (char **) addr_list; + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + i = NETDB_SUCCESS; + goto free_and_ret; } - *result = result_buf; - *h_errnop = NETDB_SUCCESS; - return NETDB_SUCCESS; + *h_errnop = HOST_NOT_FOUND; + __set_h_errno(HOST_NOT_FOUND); + i = TRY_AGAIN; + + free_and_ret: + free(a.dotted); + free(packet); + return i; #endif /* __UCLIBC_HAS_IPV6__ */ } libc_hidden_def(gethostbyname2_r) -#endif +#endif /* L_gethostbyname2_r */ + #ifdef L_gethostbyaddr_r -int gethostbyaddr_r(const void *addr, socklen_t len, int type, - struct hostent * result_buf, - char * buf, size_t buflen, - struct hostent ** result, - int * h_errnop) + +int gethostbyaddr_r(const void *addr, socklen_t addrlen, + int type, + struct hostent *result_buf, + char *buf, size_t buflen, + struct hostent **result, + int *h_errnop) { struct in_addr *in; struct in_addr **addr_list; -#ifdef __UCLIBC_HAS_IPV6__ - char *qp; - size_t plen; - struct in6_addr *in6; - struct in6_addr **addr_list6; -#endif /* __UCLIBC_HAS_IPV6__ */ char **alias; unsigned char *packet; struct resolv_answer a; int i; + int packet_len; int nest = 0; - int __nameserversXX; - char ** __nameserverXX; *result = NULL; if (!addr) return EINVAL; - memset((char *) &a, '\0', sizeof(a)); - switch (type) { +#ifdef __UCLIBC_HAS_IPV4__ case AF_INET: - if (len != sizeof(struct in_addr)) + if (addrlen != sizeof(struct in_addr)) return EINVAL; break; +#endif #ifdef __UCLIBC_HAS_IPV6__ case AF_INET6: - if (len != sizeof(struct in6_addr)) + if (addrlen != sizeof(struct in6_addr)) return EINVAL; break; -#endif /* __UCLIBC_HAS_IPV6__ */ +#endif default: return EINVAL; } /* do /etc/hosts first */ - if ((i = __get_hosts_byaddr_r(addr, len, type, result_buf, - buf, buflen, result, h_errnop)) == 0) + i = __get_hosts_byaddr_r(addr, addrlen, type, result_buf, + buf, buflen, result, h_errnop); + if (i == 0) return i; switch (*h_errnop) { case HOST_NOT_FOUND: @@ -2386,145 +2448,256 @@ int gethostbyaddr_r(const void *addr, socklen_t len, int type, return i; } - __open_nameservers(); - -#ifdef __UCLIBC_HAS_IPV6__ - qp = buf; - plen = buflen; -#endif /* __UCLIBC_HAS_IPV6__ */ - *h_errnop = NETDB_INTERNAL; - if (buflen < sizeof(*in)) - return ERANGE; + + /* make sure pointer is aligned */ + i = ALIGN_BUFFER_OFFSET(buf); + buf += i; + buflen -= i; + /* Layout in buf: + * char *alias[ALIAS_DIM]; + * struct in[6]_addr* addr_list[2]; + * struct in[6]_addr in; + * char scratch_buffer[256+]; + */ +#define in6 ((struct in6_addr *)in) + alias = (char **)buf; + addr_list = (struct in_addr**)buf; + buf += sizeof(*addr_list) * 2; + buflen -= sizeof(*addr_list) * 2; in = (struct in_addr*)buf; +#ifndef __UCLIBC_HAS_IPV6__ buf += sizeof(*in); buflen -= sizeof(*in); - - if (buflen < sizeof(*addr_list)*2) + if (addrlen > sizeof(*in)) return ERANGE; - addr_list = (struct in_addr**)buf; - buf += sizeof(*addr_list)*2; - buflen -= sizeof(*addr_list)*2; - - if (buflen < sizeof(char *)*ALIAS_DIM) +#else + buf += sizeof(*in6); + buflen -= sizeof(*in6); + if (addrlen > sizeof(*in6)) return ERANGE; - alias = (char **)buf; - buf += sizeof(*alias)*ALIAS_DIM; - buflen -= sizeof(*alias)*ALIAS_DIM; +#endif + if ((ssize_t)buflen < 256) + return ERANGE; + alias[0] = buf; + alias[1] = NULL; + addr_list[0] = in; + addr_list[1] = NULL; + memcpy(in, addr, addrlen); + if (0) /* nothing */; +#ifdef __UCLIBC_HAS_IPV4__ + else IF_HAS_BOTH(if (type == AF_INET)) { + unsigned char *tp = (unsigned char *)addr; + sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", + tp[3], tp[2], tp[1], tp[0]); + } +#endif #ifdef __UCLIBC_HAS_IPV6__ - if (plen < sizeof(*in6)) - return ERANGE; - in6 = (struct in6_addr*)qp; - qp += sizeof(*in6); - plen -= sizeof(*in6); + else { + char *dst = buf; + unsigned char *tp = (unsigned char *)addr + addrlen - 1; + do { + dst += sprintf(dst, "%x.%x.", tp[0] & 0xf, tp[0] >> 4); + tp--; + } while (tp >= (unsigned char *)addr); + strcpy(dst, "ip6.arpa"); + } +#endif - if (plen < sizeof(*addr_list6)*2) - return ERANGE; - addr_list6 = (struct in6_addr**)qp; - qp += sizeof(*addr_list6)*2; - plen -= sizeof(*addr_list6)*2; + memset(&a, '\0', sizeof(a)); + for (;;) { +/* Hmm why we memset(a) to zeros only once? */ + packet_len = __dns_lookup(buf, T_PTR, &packet, &a); + if (packet_len < 0) { + *h_errnop = HOST_NOT_FOUND; + return TRY_AGAIN; + } + + strncpy(buf, a.dotted, buflen); + free(a.dotted); + if (a.atype != T_CNAME) + break; - if (plen < buflen) { - buflen = plen; - buf = qp; + DPRINTF("Got a CNAME in gethostbyaddr()\n"); + if (++nest > MAX_RECURSE) { + *h_errnop = NO_RECOVERY; + return -1; + } + /* Decode CNAME into buf, feed it to __dns_lookup() again */ + i = __decode_dotted(packet, a.rdoffset, packet_len, buf, buflen); + free(packet); + if (i < 0) { + *h_errnop = NO_RECOVERY; + return -1; + } } -#endif /* __UCLIBC_HAS_IPV6__ */ - if (buflen < 256) - return ERANGE; + if (a.atype == T_PTR) { /* ADDRESS */ + i = __decode_dotted(packet, a.rdoffset, packet_len, buf, buflen); + free(packet); + result_buf->h_name = buf; + result_buf->h_addrtype = type; + result_buf->h_length = addrlen; + result_buf->h_addr_list = (char **) addr_list; + result_buf->h_aliases = alias; + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + return NETDB_SUCCESS; + } - if (type == AF_INET) { - unsigned char *tmp_addr = (unsigned char *)addr; + free(packet); + *h_errnop = NO_ADDRESS; + return TRY_AGAIN; +#undef in6 +} +libc_hidden_def(gethostbyaddr_r) +#endif /* L_gethostbyaddr_r */ - memcpy(&in->s_addr, addr, len); - addr_list[0] = in; +#ifdef L_gethostent_r - sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", - tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); -#ifdef __UCLIBC_HAS_IPV6__ - } else { - memcpy(in6->s6_addr, addr, len); +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); - addr_list6[0] = in6; - qp = buf; +static parser_t *hostp = NULL; +static smallint host_stayopen; - for (i = len - 1; i >= 0; i--) { - qp += sprintf(qp, "%x.%x.", in6->s6_addr[i] & 0xf, - (in6->s6_addr[i] >> 4) & 0xf); +void endhostent_unlocked(void) +{ + if (hostp) { + config_close(hostp); + hostp = NULL; + } + host_stayopen = 0; +} +void endhostent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + endhostent_unlocked(); + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +void sethostent(int stay_open) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (stay_open) + host_stayopen = 1; + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +int gethostent_r(struct hostent *result_buf, char *buf, size_t buflen, + struct hostent **result, int *h_errnop) +{ + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + if (hostp == NULL) { + hostp = __open_etc_hosts(); + if (hostp == NULL) { + *result = NULL; + ret = TRY_AGAIN; + goto DONE; } - strcpy(qp, "ip6.arpa"); -#endif /* __UCLIBC_HAS_IPV6__ */ } - addr_list[1] = 0; + ret = __read_etc_hosts_r(hostp, NULL, AF_INET, GETHOSTENT, + result_buf, buf, buflen, result, h_errnop); + if (!host_stayopen) + endhostent_unlocked(); +DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + return ret; +} +libc_hidden_def(gethostent_r) +#endif /* L_gethostent_r */ + - alias[0] = buf; - alias[1] = 0; +#ifndef __UCLIBC_HAS_IPV6__ + #define GETXX_BUFSZ (sizeof(struct in_addr) + sizeof(struct in_addr *) * 2 + \ + /*sizeof(char *)*ALIAS_DIM */+ 384/*namebuffer*/ + 32/* margin */) +#else + #define GETXX_BUFSZ (sizeof(struct in6_addr) + sizeof(struct in6_addr *) * 2 + \ + /*sizeof(char *)*ALIAS_DIM */+ 384/*namebuffer*/ + 32/* margin */) +#endif /* __UCLIBC_HAS_IPV6__ */ - for (;;) { - __UCLIBC_MUTEX_LOCK(__resolv_lock); - __nameserversXX = __nameservers; - __nameserverXX = __nameserver; - __UCLIBC_MUTEX_UNLOCK(__resolv_lock); - i = __dns_lookup(buf, T_PTR, __nameserversXX, __nameserverXX, &packet, &a); +#define __INIT_GETXX_BUF(sz) \ + if (buf == NULL) \ + buf = (char *)__uc_malloc((sz)); - if (i < 0) { - *h_errnop = HOST_NOT_FOUND; - return TRY_AGAIN; - } +#ifdef L_gethostent - strncpy(buf, a.dotted, buflen); - free(a.dotted); +struct hostent *gethostent(void) +{ + static struct hostent hoste; + static char *buf = NULL; + struct hostent *host = NULL; +#ifndef __UCLIBC_HAS_IPV6__ + #define HOSTENT_BUFSZ (sizeof(struct in_addr) + sizeof(struct in_addr *) * 2 + \ + sizeof(char *)*ALIAS_DIM + BUFSZ /*namebuffer*/ + 2 /* margin */) +#else + #define HOSTENT_BUFSZ (sizeof(struct in6_addr) + sizeof(struct in6_addr *) * 2 + \ + sizeof(char *)*ALIAS_DIM + BUFSZ /*namebuffer*/ + 2 /* margin */) +#endif /* __UCLIBC_HAS_IPV6__ */ - if (a.atype == T_CNAME) { /* CNAME */ - DPRINTF("Got a CNAME in gethostbyaddr()\n"); - i = __decode_dotted(packet, a.rdoffset, buf, buflen); - free(packet); + __INIT_GETXX_BUF(HOSTENT_BUFSZ); + gethostent_r(&hoste, buf, HOSTENT_BUFSZ, &host, &h_errno); + return host; +} +#undef HOSTENT_BUFSZ +#endif /* L_gethostent */ - if (i < 0) { - *h_errnop = NO_RECOVERY; - return -1; - } - if (++nest > MAX_RECURSE) { - *h_errnop = NO_RECOVERY; - return -1; - } - continue; - } else if (a.atype == T_PTR) { /* ADDRESS */ - i = __decode_dotted(packet, a.rdoffset, buf, buflen); - free(packet); - result_buf->h_name = buf; - result_buf->h_addrtype = type; +#ifdef L_gethostbyname2 - if (type == AF_INET) { - result_buf->h_length = sizeof(*in); -#ifdef __UCLIBC_HAS_IPV6__ - } else { - result_buf->h_length = sizeof(*in6); +struct hostent *gethostbyname2(const char *name, int family) +{ + static struct hostent hoste; + static char *buf = NULL; + struct hostent *hp; + + __INIT_GETXX_BUF(GETXX_BUFSZ); +#ifndef __UCLIBC_HAS_IPV6__ + if (family != AF_INET) + return (struct hostent*)NULL; + gethostbyname_r(name, &hoste, buf, GETXX_BUFSZ, &hp, &h_errno); +#else + gethostbyname2_r(name, family, &hoste, buf, GETXX_BUFSZ, &hp, &h_errno); #endif /* __UCLIBC_HAS_IPV6__ */ - } - result_buf->h_addr_list = (char **) addr_list; - result_buf->h_aliases = alias; - break; - } else { - free(packet); - *h_errnop = NO_ADDRESS; - return TRY_AGAIN; - } - } + return hp; +} +libc_hidden_def(gethostbyname2) +#endif /* L_gethostbyname2 */ - *result = result_buf; - *h_errnop = NETDB_SUCCESS; - return NETDB_SUCCESS; + +#ifdef L_gethostbyname + +struct hostent *gethostbyname(const char *name) +{ + return gethostbyname2(name, AF_INET); } -libc_hidden_def(gethostbyaddr_r) -#endif +libc_hidden_def(gethostbyname) +#endif /* L_gethostbyname */ + + +#ifdef L_gethostbyaddr + +struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) +{ + static struct hostent hoste; + static char *buf = NULL; + struct hostent *hp; + + __INIT_GETXX_BUF(GETXX_BUFSZ); + gethostbyaddr_r(addr, len, type, &hoste, buf, GETXX_BUFSZ, &hp, &h_errno); + return hp; +} +libc_hidden_def(gethostbyaddr) +#endif /* L_gethostbyaddr */ + #ifdef L_res_comp + /* * Expand compressed domain name 'comp_dn' to full domain name. * 'msg' is a pointer to the begining of the message, @@ -2532,7 +2705,7 @@ libc_hidden_def(gethostbyaddr_r) * 'exp_dn' is a pointer to a buffer of size 'length' for the result. * Return size of compressed name or -1 if there was an error. */ -int __dn_expand(const u_char *msg, const u_char *eom, const u_char *src, +int dn_expand(const u_char *msg, const u_char *eom, const u_char *src, char *dst, int dstsiz) { int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); @@ -2541,27 +2714,36 @@ int __dn_expand(const u_char *msg, const u_char *eom, const u_char *src, dst[0] = '\0'; return n; } +libc_hidden_def(dn_expand) + +/* + * Pack domain name 'exp_dn' in presentation form into 'comp_dn'. + * Return the size of the compressed name or -1. + * 'length' is the size of the array pointed to by 'comp_dn'. + */ +int +dn_comp(const char *src, u_char *dst, int dstsiz, + u_char **dnptrs, u_char **lastdnptr) +{ + return ns_name_compress(src, dst, (size_t) dstsiz, + (const u_char **) dnptrs, + (const u_char **) lastdnptr); +} +libc_hidden_def(dn_comp) #endif /* L_res_comp */ + #ifdef L_ns_name -/* - * printable(ch) - * Thinking in noninternationalized USASCII (per the DNS spec), - * is this character visible and not a space when printed ? - * return: - * boolean. + +/* Thinking in noninternationalized USASCII (per the DNS spec), + * is this character visible and not a space when printed ? */ static int printable(int ch) { return (ch > 0x20 && ch < 0x7f); } - -/* - * special(ch) - * Thinking in noninternationalized USASCII (per the DNS spec), - * is this characted special ("in need of quoting") ? - * return: - * boolean. +/* Thinking in noninternationalized USASCII (per the DNS spec), + * is this characted special ("in need of quoting") ? */ static int special(int ch) { @@ -2593,7 +2775,8 @@ int ns_name_uncompress(const u_char *msg, const u_char *eom, u_char tmp[NS_MAXCDNAME]; int n; - if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) + n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp); + if (n == -1) return -1; if (ns_name_ntop(tmp, dst, dstsiz) == -1) return -1; @@ -2601,7 +2784,6 @@ int ns_name_uncompress(const u_char *msg, const u_char *eom, } libc_hidden_def(ns_name_uncompress) - /* * ns_name_ntop(src, dst, dstsiz) * Convert an encoded domain name to printable ascii as per RFC1035. @@ -2611,12 +2793,12 @@ libc_hidden_def(ns_name_uncompress) * The root is returned as "." * All other domains are returned in non absolute form */ -int ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) { +int ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) +{ const u_char *cp; char *dn, *eom; u_char c; u_int n; - const char digits[] = "0123456789"; cp = src; dn = dst; @@ -2639,7 +2821,7 @@ int ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) { __set_errno(EMSGSIZE); return -1; } - for ((void)NULL; n > 0; n--) { + for (; n > 0; n--) { c = *cp++; if (special(c)) { if (dn + 1 >= eom) { @@ -2654,9 +2836,10 @@ int ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) { return -1; } *dn++ = '\\'; - *dn++ = digits[c / 100]; - *dn++ = digits[(c % 100) / 10]; - *dn++ = digits[c % 10]; + *dn++ = "0123456789"[c / 100]; + c = c % 100; + *dn++ = "0123456789"[c / 10]; + *dn++ = "0123456789"[c % 10]; } else { if (dn >= eom) { __set_errno(EMSGSIZE); @@ -2682,6 +2865,241 @@ int ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) { } libc_hidden_def(ns_name_ntop) +static int encode_bitstring(const char **bp, const char *end, + unsigned char **labelp, + unsigned char ** dst, + unsigned const char *eom) +{ + int afterslash = 0; + const char *cp = *bp; + unsigned char *tp; + const char *beg_blen; + int value = 0, count = 0, tbcount = 0, blen = 0; + + beg_blen = NULL; + + /* a bitstring must contain at least 2 characters */ + if (end - cp < 2) + return EINVAL; + + /* XXX: currently, only hex strings are supported */ + if (*cp++ != 'x') + return EINVAL; + if (!isxdigit((unsigned char) *cp)) /*%< reject '\[x/BLEN]' */ + return EINVAL; + + for (tp = *dst + 1; cp < end && tp < eom; cp++) { + unsigned char c = *cp; + + switch (c) { + case ']': /*%< end of the bitstring */ + if (afterslash) { + char *end_blen; + if (beg_blen == NULL) + return EINVAL; + blen = (int)strtol(beg_blen, &end_blen, 10); + if (*end_blen != ']') + return EINVAL; + } + if (count) + *tp++ = ((value << 4) & 0xff); + cp++; /*%< skip ']' */ + goto done; + case '/': + afterslash = 1; + break; + default: + if (afterslash) { + if (!__isdigit_char(c)) + return EINVAL; + if (beg_blen == NULL) { + if (c == '0') { + /* blen never begings with 0 */ + return EINVAL; + } + beg_blen = cp; + } + } else { + if (!__isdigit_char(c)) { + c = c | 0x20; /* lowercase */ + c = c - 'a'; + if (c > 5) /* not a-f? */ + return EINVAL; + c += 10 + '0'; + } + value <<= 4; + value += (c - '0'); + count += 4; + tbcount += 4; + if (tbcount > 256) + return EINVAL; + if (count == 8) { + *tp++ = value; + count = 0; + } + } + break; + } + } + done: + if (cp >= end || tp >= eom) + return EMSGSIZE; + + /* + * bit length validation: + * If a <length> is present, the number of digits in the <bit-data> + * MUST be just sufficient to contain the number of bits specified + * by the <length>. If there are insignificant bits in a final + * hexadecimal or octal digit, they MUST be zero. + * RFC2673, Section 3.2. + */ + if (blen > 0) { + int traillen; + + if (((blen + 3) & ~3) != tbcount) + return EINVAL; + traillen = tbcount - blen; /*%< between 0 and 3 */ + if (((value << (8 - traillen)) & 0xff) != 0) + return EINVAL; + } + else + blen = tbcount; + if (blen == 256) + blen = 0; + + /* encode the type and the significant bit fields */ + **labelp = DNS_LABELTYPE_BITSTRING; + **dst = blen; + + *bp = cp; + *dst = tp; + + return 0; +} + +int ns_name_pton(const char *src, u_char *dst, size_t dstsiz) +{ + static const char digits[] = "0123456789"; + u_char *label, *bp, *eom; + int c, n, escaped, e = 0; + char *cp; + + escaped = 0; + bp = dst; + eom = dst + dstsiz; + label = bp++; + + while ((c = *src++) != 0) { + if (escaped) { + if (c == '[') { /*%< start a bit string label */ + cp = strchr(src, ']'); + if (cp == NULL) { + errno = EINVAL; /*%< ??? */ + return -1; + } + e = encode_bitstring(&src, cp + 2, + &label, &bp, eom); + if (e != 0) { + errno = e; + return -1; + } + escaped = 0; + label = bp++; + c = *src++; + if (c == '\0') + goto done; + if (c != '.') { + errno = EINVAL; + return -1; + } + continue; + } + cp = strchr(digits, c); + if (cp != NULL) { + n = (cp - digits) * 100; + c = *src++; + if (c == '\0') + goto ret_EMSGSIZE; + cp = strchr(digits, c); + if (cp == NULL) + goto ret_EMSGSIZE; + n += (cp - digits) * 10; + c = *src++; + if (c == '\0') + goto ret_EMSGSIZE; + cp = strchr(digits, c); + if (cp == NULL) + goto ret_EMSGSIZE; + n += (cp - digits); + if (n > 255) + goto ret_EMSGSIZE; + c = n; + } + escaped = 0; + } else if (c == '\\') { + escaped = 1; + continue; + } else if (c == '.') { + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */ + goto ret_EMSGSIZE; + } + if (label >= eom) { + goto ret_EMSGSIZE; + } + *label = c; + /* Fully qualified ? */ + if (*src == '\0') { + if (c != 0) { + if (bp >= eom) { + goto ret_EMSGSIZE; + } + *bp++ = '\0'; + } + if ((bp - dst) > MAXCDNAME) { + goto ret_EMSGSIZE; + } + + return 1; + } + if (c == 0 || *src == '.') { + goto ret_EMSGSIZE; + } + label = bp++; + continue; + } + if (bp >= eom) { + goto ret_EMSGSIZE; + } + *bp++ = (u_char)c; + } + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */ + goto ret_EMSGSIZE; + } + done: + if (label >= eom) { + goto ret_EMSGSIZE; + } + *label = c; + if (c != 0) { + if (bp >= eom) { + goto ret_EMSGSIZE; + } + *bp++ = 0; + } + if ((bp - dst) > MAXCDNAME) { /*%< src too big */ + goto ret_EMSGSIZE; + } + + return 0; + + ret_EMSGSIZE: + errno = EMSGSIZE; + return -1; +} +libc_hidden_def(ns_name_pton) + /* * ns_name_unpack(msg, eom, src, dst, dstsiz) * Unpack a domain name from a message, source may be compressed. @@ -2756,5 +3174,1193 @@ int ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, return len; } libc_hidden_def(ns_name_unpack) + +static int labellen(const unsigned char *lp) +{ + unsigned bitlen; + unsigned char l = *lp; + + if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* should be avoided by the caller */ + return -1; + } + + if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) { + if (l == DNS_LABELTYPE_BITSTRING) { + bitlen = lp[1]; + if (bitlen == 0) + bitlen = 256; + return ((bitlen + 7 ) / 8 + 1); + } + + return -1; /*%< unknwon ELT */ + } + + return l; +} + +static int mklower(int ch) +{ + if (ch >= 0x41 && ch <= 0x5A) + return (ch + 0x20); + + return ch; +} + +static int dn_find(const unsigned char *domain, + const unsigned char *msg, + const unsigned char * const *dnptrs, + const unsigned char * const *lastdnptr) +{ + const unsigned char *dn, *cp, *sp; + const unsigned char * const *cpp; + u_int n; + + for (cpp = dnptrs; cpp < lastdnptr; cpp++) { + sp = *cpp; + /* + * terminate search on: + * root label + * compression pointer + * unusable offset + */ + while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 && + (sp - msg) < 0x4000) { + dn = domain; + cp = sp; + + while ((n = *cp++) != 0) { + /* + * check for indirection + */ + switch (n & NS_CMPRSFLGS) { + case 0: /*%< normal case, n == len */ + n = labellen(cp - 1); /*%< XXX */ + if (n != *dn++) + goto next; + + for (; n > 0; n--) + if (mklower(*dn++) != + mklower(*cp++)) + goto next; + /* Is next root for both ? */ + if (*dn == '\0' && *cp == '\0') + return (sp - msg); + if (*dn) + continue; + goto next; + case NS_CMPRSFLGS: /*%< indirection */ + cp = msg + (((n & 0x3f) << 8) | *cp); + break; + + default: /*%< illegal type */ + errno = EMSGSIZE; + return -1; + } + } +next: + sp += *sp + 1; + } + } + + errno = ENOENT; + return -1; +} + +int ns_name_pack(const unsigned char *src, + unsigned char *dst, int dstsiz, + const unsigned char **dnptrs, + const unsigned char **lastdnptr) +{ + unsigned char *dstp; + const unsigned char **cpp, **lpp, *eob, *msg; + const unsigned char *srcp; + int n, l, first = 1; + + srcp = src; + dstp = dst; + eob = dstp + dstsiz; + lpp = cpp = NULL; + + if (dnptrs != NULL) { + msg = *dnptrs++; + if (msg != NULL) { + for (cpp = dnptrs; *cpp != NULL; cpp++) + continue; + + lpp = cpp; /*%< end of list to search */ + } + } else { + msg = NULL; + } + + /* make sure the domain we are about to add is legal */ + l = 0; + do { + int l0; + + n = *srcp; + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + errno = EMSGSIZE; + return -1; + } + + l0 = labellen(srcp); + if (l0 < 0) { + errno = EINVAL; + return -1; + } + + l += l0 + 1; + if (l > MAXCDNAME) { + errno = EMSGSIZE; + return -1; + } + + srcp += l0 + 1; + } while (n != 0); + + /* from here on we need to reset compression pointer array on error */ + srcp = src; + + do { + /* Look to see if we can use pointers. */ + n = *srcp; + + if (n != 0 && msg != NULL) { + l = dn_find(srcp, msg, (const unsigned char * const *) dnptrs, + (const unsigned char * const *) lpp); + if (l >= 0) { + if (dstp + 1 >= eob) { + goto cleanup; + } + + *dstp++ = ((u_int32_t)l >> 8) | NS_CMPRSFLGS; + *dstp++ = l % 256; + return (dstp - dst); + } + + /* Not found, save it. */ + if (lastdnptr != NULL && cpp < lastdnptr - 1 && + (dstp - msg) < 0x4000 && first) { + *cpp++ = dstp; + *cpp = NULL; + first = 0; + } + } + + /* copy label to buffer */ + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Should not happen. */ + goto cleanup; + } + + n = labellen(srcp); + if (dstp + 1 + n >= eob) { + goto cleanup; + } + + memcpy(dstp, srcp, (size_t)(n + 1)); + srcp += n + 1; + dstp += n + 1; + } while (n != 0); + + if (dstp > eob) { +cleanup: + if (msg != NULL) + *lpp = NULL; + + errno = EMSGSIZE; + return -1; + } + + return dstp - dst; +} +libc_hidden_def(ns_name_pack) + +int ns_name_compress(const char *src, + unsigned char *dst, size_t dstsiz, + const unsigned char **dnptrs, + const unsigned char **lastdnptr) +{ + unsigned char tmp[NS_MAXCDNAME]; + + if (ns_name_pton(src, tmp, sizeof(tmp)) == -1) + return -1; + + return ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr); +} +libc_hidden_def(ns_name_compress) + +int ns_name_skip(const unsigned char **ptrptr, + const unsigned char *eom) +{ + const unsigned char *cp; + u_int n; + int l; + + cp = *ptrptr; + while (cp < eom && (n = *cp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: /*%< normal case, n == len */ + cp += n; + continue; + case NS_TYPE_ELT: /*%< EDNS0 extended label */ + l = labellen(cp - 1); + if (l < 0) { + errno = EMSGSIZE; /*%< XXX */ + return -1; + } + cp += l; + continue; + case NS_CMPRSFLGS: /*%< indirection */ + cp++; + break; + default: /*%< illegal type */ + errno = EMSGSIZE; + return -1; + } + + break; + } + + if (cp > eom) { + errno = EMSGSIZE; + return -1; + } + + *ptrptr = cp; + + return 0; +} +libc_hidden_def(ns_name_skip) + +int dn_skipname(const unsigned char *ptr, const unsigned char *eom) +{ + const unsigned char *saveptr = ptr; + + if (ns_name_skip(&ptr, eom) == -1) + return -1; + + return ptr - saveptr; +} +libc_hidden_def(dn_skipname) #endif /* L_ns_name */ -/* vi: set sw=4 ts=4: */ + + +#ifdef L_res_init + +/* Will be called under __resolv_lock. */ +static void res_sync_func(void) +{ + struct __res_state *rp = &(_res); + int n; + + /* If we didn't get malloc failure earlier... */ + if (__nameserver != (void*) &__local_nameserver) { + /* TODO: + * if (__nameservers < rp->nscount) - try to grow __nameserver[]? + */ +#ifdef __UCLIBC_HAS_IPV6__ + if (__nameservers > rp->_u._ext.nscount) + __nameservers = rp->_u._ext.nscount; + n = __nameservers; + while (--n >= 0) + __nameserver[n].sa6 = *rp->_u._ext.nsaddrs[n]; /* struct copy */ +#else /* IPv4 only */ + if (__nameservers > rp->nscount) + __nameservers = rp->nscount; + n = __nameservers; + while (--n >= 0) + __nameserver[n].sa4 = rp->nsaddr_list[n]; /* struct copy */ +#endif + } + __resolv_timeout = rp->retrans ? : RES_TIMEOUT; + __resolv_attempts = rp->retry ? : RES_DFLRETRY; + /* Extend and comment what program is known + * to use which _res.XXX member(s). + + __resolv_opts = rp->options; + ... + */ +} + +/* has to be called under __resolv_lock */ +static int +__res_vinit(res_state rp, int preinit) +{ + int i, n, options, retrans, retry, ndots; +#ifdef __UCLIBC_HAS_IPV6__ + int m = 0; +#endif + + __close_nameservers(); + __open_nameservers(); + + if (preinit) { + options = rp->options; + retrans = rp->retrans; + retry = rp->retry; + ndots = rp->ndots; + } + + memset(rp, 0, sizeof(*rp)); + + if (!preinit) { + rp->options = RES_DEFAULT; + rp->retrans = RES_TIMEOUT; + rp->retry = RES_DFLRETRY; + rp->ndots = 1; + } else { + rp->options = options; + rp->retrans = retrans; + rp->retry = retry; + rp->ndots = ndots; + } + +#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__ + /* Was: "rp->id = random();" but: + * - random() pulls in largish static buffers + * - isn't actually random unless, say, srandom(time(NULL)) was called + * - is not used by uclibc anyway :) + */ + /* rp->id = 0; - memset did it */ +#endif +#ifdef __UCLIBC_HAS_EXTRA_COMPAT_RES_STATE__ + rp->_vcsock = -1; +#endif + + n = __searchdomains; + if (n > ARRAY_SIZE(rp->dnsrch)) + n = ARRAY_SIZE(rp->dnsrch); + for (i = 0; i < n; i++) + rp->dnsrch[i] = __searchdomain[i]; + + /* copy nameservers' addresses */ + i = 0; +#ifdef __UCLIBC_HAS_IPV4__ + n = 0; + while (n < ARRAY_SIZE(rp->nsaddr_list) && i < __nameservers) { + if (__nameserver[i].sa.sa_family == AF_INET) { + rp->nsaddr_list[n] = __nameserver[i].sa4; /* struct copy */ +#ifdef __UCLIBC_HAS_IPV6__ + if (m < ARRAY_SIZE(rp->_u._ext.nsaddrs)) { + rp->_u._ext.nsaddrs[m] = (void*) &rp->nsaddr_list[n]; + m++; + } +#endif + n++; + } +#ifdef __UCLIBC_HAS_IPV6__ + if (__nameserver[i].sa.sa_family == AF_INET6 + && m < ARRAY_SIZE(rp->_u._ext.nsaddrs) + ) { + struct sockaddr_in6 *sa6 = malloc(sizeof(*sa6)); + if (sa6) { + *sa6 = __nameserver[i].sa6; /* struct copy */ + rp->_u._ext.nsaddrs[m] = sa6; + m++; + } + } +#endif + i++; + } + rp->nscount = n; +#ifdef __UCLIBC_HAS_IPV6__ + rp->_u._ext.nscount = m; +#endif + +#else /* IPv6 only */ + while (m < ARRAY_SIZE(rp->_u._ext.nsaddrs) && i < __nameservers) { + struct sockaddr_in6 *sa6 = malloc(sizeof(*sa6)); + if (sa6) { + *sa6 = __nameserver[i].sa6; /* struct copy */ + rp->_u._ext.nsaddrs[m] = sa6; + m++; + } + i++; + } + rp->_u._ext.nscount = m; +#endif + + rp->options |= RES_INIT; + + return 0; +} + +static unsigned int +res_randomid(void) +{ + return 0xffff & getpid(); +} + +/* Our res_init never fails (always returns 0) */ +int +res_init(void) +{ + /* + * These three fields used to be statically initialized. This made + * it hard to use this code in a shared library. It is necessary, + * now that we're doing dynamic initialization here, that we preserve + * the old semantics: if an application modifies one of these three + * fields of _res before res_init() is called, res_init() will not + * alter them. Of course, if an application is setting them to + * _zero_ before calling res_init(), hoping to override what used + * to be the static default, we can't detect it and unexpected results + * will follow. Zero for any of these fields would make no sense, + * so one can safely assume that the applications were already getting + * unexpected results. + * + * _res.options is tricky since some apps were known to diddle the bits + * before res_init() was first called. We can't replicate that semantic + * with dynamic initialization (they may have turned bits off that are + * set in RES_DEFAULT). Our solution is to declare such applications + * "broken". They could fool us by setting RES_INIT but none do (yet). + */ + + __UCLIBC_MUTEX_LOCK(__resolv_lock); + + if (!_res.retrans) + _res.retrans = RES_TIMEOUT; + if (!_res.retry) + _res.retry = 4; + if (!(_res.options & RES_INIT)) + _res.options = RES_DEFAULT; + + /* + * This one used to initialize implicitly to zero, so unless the app + * has set it to something in particular, we can randomize it now. + */ + if (!_res.id) + _res.id = res_randomid(); + + __res_sync = NULL; + __res_vinit(&_res, 1); + __res_sync = res_sync_func; + + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + + return 0; +} +libc_hidden_def(res_init) + +static void +__res_iclose(res_state statp) +{ + struct __res_state * rp = statp; + __UCLIBC_MUTEX_LOCK(__resolv_lock); + if (rp == NULL) + rp = __res_state(); + __close_nameservers(); + __res_sync = NULL; +#ifdef __UCLIBC_HAS_IPV6__ + { + char *p1 = (char*) &(rp->nsaddr_list[0]); + unsigned int m = 0; + /* free nsaddrs[m] if they do not point to nsaddr_list[x] */ + while (m < ARRAY_SIZE(rp->_u._ext.nsaddrs)) { + char *p2 = (char*)(rp->_u._ext.nsaddrs[m++]); + if (p2 < p1 || (p2 - p1) > (signed)sizeof(rp->nsaddr_list)) + free(p2); + } + } +#endif + memset(rp, 0, sizeof(struct __res_state)); + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); +} + +/* + * This routine is for closing the socket if a virtual circuit is used and + * the program wants to close it. This provides support for endhostent() + * which expects to close the socket. + * + * This routine is not expected to be user visible. + */ + +void +res_nclose(res_state statp) +{ + __res_iclose(statp); +} + +#ifdef __UCLIBC_HAS_BSD_RES_CLOSE__ +void res_close(void) +{ + __res_iclose(NULL); +} +#endif + +/* This needs to be after the use of _res in res_init, above. */ +#undef _res + +#ifndef __UCLIBC_HAS_THREADS__ +/* The resolver state for use by single-threaded programs. + This differs from plain `struct __res_state _res;' in that it doesn't + create a common definition, but a plain symbol that resides in .bss, + which can have an alias. */ +struct __res_state _res __attribute__((section (".bss"))); +struct __res_state *__resp = &_res; +#else /* __UCLIBC_HAS_THREADS__ */ +struct __res_state _res __attribute__((section (".bss"))) attribute_hidden; + +# if defined __UCLIBC_HAS_TLS__ +# undef __resp +__thread struct __res_state *__resp = &_res; +extern __thread struct __res_state *__libc_resp + __attribute__ ((alias ("__resp"))) attribute_hidden attribute_tls_model_ie; +# else +# undef __resp +struct __res_state *__resp = &_res; +# endif +#endif /* !__UCLIBC_HAS_THREADS__ */ + +/* + * Set up default settings. If the configuration file exist, the values + * there will have precedence. Otherwise, the server address is set to + * INADDR_ANY and the default domain name comes from the gethostname(). + * + * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 + * rather than INADDR_ANY ("0.0.0.0") as the default name server address + * since it was noted that INADDR_ANY actually meant ``the first interface + * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, + * it had to be "up" in order for you to reach your own name server. It + * was later decided that since the recommended practice is to always + * install local static routes through 127.0.0.1 for all your network + * interfaces, that we could solve this problem without a code change. + * + * The configuration file should always be used, since it is the only way + * to specify a default domain. If you are running a server on your local + * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" + * in the configuration file. + * + * Return 0 if completes successfully, -1 on error + */ +int +res_ninit(res_state statp) +{ + int ret; + __UCLIBC_MUTEX_LOCK(__resolv_lock); + ret = __res_vinit(statp, 0); + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + return ret; +} + +#endif /* L_res_init */ + +#ifdef L_res_state +# if defined __UCLIBC_HAS_TLS__ +struct __res_state * +__res_state (void) +{ + return __resp; +} +# else +# undef _res +extern struct __res_state _res; + +/* When threaded, _res may be a per-thread variable. */ +struct __res_state * +weak_const_function +__res_state (void) +{ + return &_res; +} +# endif + +#endif /* L_res_state */ + + +#ifdef L_res_query + +int res_query(const char *dname, int class, int type, + unsigned char *answer, int anslen) +{ + int i; + unsigned char *packet = NULL; + struct resolv_answer a; + + if (!dname || class != 1 /* CLASS_IN */) { + h_errno = NO_RECOVERY; + return -1; + } + + memset(&a, '\0', sizeof(a)); + i = __dns_lookup(dname, type, &packet, &a); + + if (i < 0) { + if (!h_errno) /* TODO: can this ever happen? */ + h_errno = TRY_AGAIN; + return -1; + } + + free(a.dotted); + + if (i > anslen) + i = anslen; + memcpy(answer, packet, i); + + free(packet); + return i; +} +libc_hidden_def(res_query) + +/* + * Formulate a normal query, send, and retrieve answer in supplied buffer. + * Return the size of the response on success, -1 on error. + * If enabled, implement search rules until answer or unrecoverable failure + * is detected. Error code, if any, is left in h_errno. + */ +#define __TRAILING_DOT (1<<0) +#define __GOT_NODATA (1<<1) +#define __GOT_SERVFAIL (1<<2) +#define __TRIED_AS_IS (1<<3) +int res_search(const char *name, int class, int type, u_char *answer, + int anslen) +{ + const char *cp; + char **domain; + HEADER *hp = (HEADER *)(void *)answer; + unsigned dots; + unsigned state; + int ret, saved_herrno; + uint32_t _res_options; + unsigned _res_ndots; + char **_res_dnsrch; + + if (!name || !answer) { + h_errno = NETDB_INTERNAL; + return -1; + } + + again: + __UCLIBC_MUTEX_LOCK(__resolv_lock); + _res_options = _res.options; + _res_ndots = _res.ndots; + _res_dnsrch = _res.dnsrch; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + if (!(_res_options & RES_INIT)) { + res_init(); /* our res_init never fails */ + goto again; + } + + state = 0; + errno = 0; + h_errno = HOST_NOT_FOUND; /* default, if we never query */ + dots = 0; + for (cp = name; *cp; cp++) + dots += (*cp == '.'); + + if (cp > name && *--cp == '.') + state |= __TRAILING_DOT; + + /* + * If there are dots in the name already, let's just give it a try + * 'as is'. The threshold can be set with the "ndots" option. + */ + saved_herrno = -1; + if (dots >= _res_ndots) { + ret = res_querydomain(name, NULL, class, type, answer, anslen); + if (ret > 0) + return ret; + saved_herrno = h_errno; + state |= __TRIED_AS_IS; + } + + /* + * We do at least one level of search if + * - there is no dot and RES_DEFNAME is set, or + * - there is at least one dot, there is no trailing dot, + * and RES_DNSRCH is set. + */ + if ((!dots && (_res_options & RES_DEFNAMES)) + || (dots && !(state & __TRAILING_DOT) && (_res_options & RES_DNSRCH)) + ) { + bool done = 0; + + for (domain = _res_dnsrch; *domain && !done; domain++) { + + ret = res_querydomain(name, *domain, class, type, + answer, anslen); + if (ret > 0) + return ret; + + /* + * If no server present, give up. + * If name isn't found in this domain, + * keep trying higher domains in the search list + * (if that's enabled). + * On a NO_DATA error, keep trying, otherwise + * a wildcard entry of another type could keep us + * from finding this entry higher in the domain. + * If we get some other error (negative answer or + * server failure), then stop searching up, + * but try the input name below in case it's + * fully-qualified. + */ + if (errno == ECONNREFUSED) { + h_errno = TRY_AGAIN; + return -1; + } + + switch (h_errno) { + case NO_DATA: + state |= __GOT_NODATA; + /* FALLTHROUGH */ + case HOST_NOT_FOUND: + /* keep trying */ + break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) { + /* try next search element, if any */ + state |= __GOT_SERVFAIL; + break; + } + /* FALLTHROUGH */ + default: + /* anything else implies that we're done */ + done = 1; + } + /* + * if we got here for some reason other than DNSRCH, + * we only wanted one iteration of the loop, so stop. + */ + if (!(_res_options & RES_DNSRCH)) + done = 1; + } + } + + /* + * if we have not already tried the name "as is", do that now. + * note that we do this regardless of how many dots were in the + * name or whether it ends with a dot. + */ + if (!(state & __TRIED_AS_IS)) { + ret = res_querydomain(name, NULL, class, type, answer, anslen); + if (ret > 0) + return ret; + } + + /* + * if we got here, we didn't satisfy the search. + * if we did an initial full query, return that query's h_errno + * (note that we wouldn't be here if that query had succeeded). + * else if we ever got a nodata, send that back as the reason. + * else send back meaningless h_errno, that being the one from + * the last DNSRCH we did. + */ + if (saved_herrno != -1) + h_errno = saved_herrno; + else if (state & __GOT_NODATA) + h_errno = NO_DATA; + else if (state & __GOT_SERVFAIL) + h_errno = TRY_AGAIN; + return -1; +} +#undef __TRAILING_DOT +#undef __GOT_NODATA +#undef __GOT_SERVFAIL +#undef __TRIED_AS_IS +/* + * Perform a call on res_query on the concatenation of name and domain, + * removing a trailing dot from name if domain is NULL. + */ +int res_querydomain(const char *name, const char *domain, int class, int type, + u_char *answer, int anslen) +{ + char nbuf[MAXDNAME]; + const char *longname = nbuf; + size_t n, d; +#ifdef DEBUG + uint32_t _res_options; +#endif + + if (!name || !answer) { + h_errno = NETDB_INTERNAL; + return -1; + } + +#ifdef DEBUG + again: + __UCLIBC_MUTEX_LOCK(__resolv_lock); + _res_options = _res.options; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + if (!(_res_options & RES_INIT)) { + res_init(); /* our res_init never fails */ + goto again; + } + if (_res_options & RES_DEBUG) + printf(";; res_querydomain(%s, %s, %d, %d)\n", + name, (domain ? domain : "<Nil>"), class, type); +#endif + if (domain == NULL) { + /* + * Check for trailing '.'; + * copy without '.' if present. + */ + n = strlen(name); + if (n + 1 > sizeof(nbuf)) { + h_errno = NO_RECOVERY; + return -1; + } + if (n > 0 && name[--n] == '.') { + strncpy(nbuf, name, n); + nbuf[n] = '\0'; + } else + longname = name; + } else { + n = strlen(name); + d = strlen(domain); + if (n + 1 + d + 1 > sizeof(nbuf)) { + h_errno = NO_RECOVERY; + return -1; + } + snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); + } + return res_query(longname, class, type, answer, anslen); +} +libc_hidden_def(res_querydomain) +#endif /* L_res_query */ + +#ifdef L_ns_netint +unsigned int ns_get16(const unsigned char *src) +{ + unsigned int dst; + NS_GET16(dst, src); + return dst; +} + +unsigned long ns_get32(const unsigned char *src) +{ + unsigned long dst; + NS_GET32(dst, src); + return dst; +} + +void ns_put16(unsigned int src, unsigned char *dst) +{ + NS_PUT16(src, dst); +} + +void ns_put32(unsigned long src, unsigned char *dst) +{ + NS_PUT32(src, dst); +} +#endif /* L_ns_netint */ + +#ifdef L_ns_parse +/* These need to be in the same order as the nres.h:ns_flag enum. */ +struct _ns_flagdata { unsigned short mask, shift; }; +static const struct _ns_flagdata _ns_flagdata[16] = { + { 0x8000, 15 }, /*%< qr. */ + { 0x7800, 11 }, /*%< opcode. */ + { 0x0400, 10 }, /*%< aa. */ + { 0x0200, 9 }, /*%< tc. */ + { 0x0100, 8 }, /*%< rd. */ + { 0x0080, 7 }, /*%< ra. */ + { 0x0040, 6 }, /*%< z. */ + { 0x0020, 5 }, /*%< ad. */ + { 0x0010, 4 }, /*%< cd. */ + { 0x000f, 0 }, /*%< rcode. */ + { 0x0000, 0 }, /*%< expansion (1/6). */ + { 0x0000, 0 }, /*%< expansion (2/6). */ + { 0x0000, 0 }, /*%< expansion (3/6). */ + { 0x0000, 0 }, /*%< expansion (4/6). */ + { 0x0000, 0 }, /*%< expansion (5/6). */ + { 0x0000, 0 }, /*%< expansion (6/6). */ +}; + +static void setsection(ns_msg *msg, ns_sect sect) +{ + msg->_sect = sect; + if (sect == ns_s_max) { + msg->_rrnum = -1; + msg->_ptr = NULL; + } else { + msg->_rrnum = 0; + msg->_ptr = msg->_sections[(int)sect]; + } +} + +int ns_skiprr(const unsigned char *ptr, + const unsigned char *eom, + ns_sect section, int count) +{ + const u_char *optr = ptr; + + for (; count > 0; count--) { + int b, rdlength; + + b = dn_skipname(ptr, eom); + if (b < 0) { + errno = EMSGSIZE; + return -1; + } + + ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; + if (section != ns_s_qd) { + if (ptr + NS_INT32SZ + NS_INT16SZ > eom) { + errno = EMSGSIZE; + return -1; + } + + ptr += NS_INT32SZ/*TTL*/; + NS_GET16(rdlength, ptr); + ptr += rdlength/*RData*/; + } + } + + if (ptr > eom) { + errno = EMSGSIZE; + return -1; + } + + return ptr - optr; +} +libc_hidden_def(ns_skiprr) + +int +ns_initparse(const unsigned char *msg, int msglen, ns_msg *handle) +{ + const u_char *eom = msg + msglen; + int i; + + handle->_msg = msg; + handle->_eom = eom; + if (msg + NS_INT16SZ > eom) { + errno = EMSGSIZE; + return -1; + } + + NS_GET16(handle->_id, msg); + if (msg + NS_INT16SZ > eom) { + errno = EMSGSIZE; + return -1; + } + + NS_GET16(handle->_flags, msg); + for (i = 0; i < ns_s_max; i++) { + if (msg + NS_INT16SZ > eom) { + errno = EMSGSIZE; + return -1; + } + + NS_GET16(handle->_counts[i], msg); + } + for (i = 0; i < ns_s_max; i++) + if (handle->_counts[i] == 0) + handle->_sections[i] = NULL; + else { + int b = ns_skiprr(msg, eom, (ns_sect)i, + handle->_counts[i]); + + if (b < 0) + return -1; + handle->_sections[i] = msg; + msg += b; + } + + if (msg != eom) { + errno = EMSGSIZE; + return -1; + } + + setsection(handle, ns_s_max); + return 0; +} + +int +ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) +{ + int b; + int tmp; + + /* Make section right. */ + tmp = section; + if (tmp < 0 || section >= ns_s_max) { + errno = ENODEV; + return -1; + } + + if (section != handle->_sect) + setsection(handle, section); + + /* Make rrnum right. */ + if (rrnum == -1) + rrnum = handle->_rrnum; + if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) { + errno = ENODEV; + return -1; + } + if (rrnum < handle->_rrnum) + setsection(handle, section); + if (rrnum > handle->_rrnum) { + b = ns_skiprr(handle->_ptr, handle->_eom, section, + rrnum - handle->_rrnum); + + if (b < 0) + return -1; + handle->_ptr += b; + handle->_rrnum = rrnum; + } + + /* Do the parse. */ + b = dn_expand(handle->_msg, handle->_eom, + handle->_ptr, rr->name, NS_MAXDNAME); + if (b < 0) + return -1; + handle->_ptr += b; + if (handle->_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) { + errno = EMSGSIZE; + return -1; + } + NS_GET16(rr->type, handle->_ptr); + NS_GET16(rr->rr_class, handle->_ptr); + if (section == ns_s_qd) { + rr->ttl = 0; + rr->rdlength = 0; + rr->rdata = NULL; + } else { + if (handle->_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) { + errno = EMSGSIZE; + return -1; + } + NS_GET32(rr->ttl, handle->_ptr); + NS_GET16(rr->rdlength, handle->_ptr); + if (handle->_ptr + rr->rdlength > handle->_eom) { + errno = EMSGSIZE; + return -1; + } + rr->rdata = handle->_ptr; + handle->_ptr += rr->rdlength; + } + if (++handle->_rrnum > handle->_counts[(int)section]) + setsection(handle, (ns_sect)((int)section + 1)); + + return 0; +} + +int ns_msg_getflag(ns_msg handle, int flag) +{ + return ((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift; +} +#endif /* L_ns_parse */ + +#ifdef L_res_data +int res_mkquery(int op, const char *dname, int class, int type, + const unsigned char *data, int datalen, + const unsigned char *newrr_in, + unsigned char *buf, int buflen) +{ + HEADER *hp; + unsigned char *cp, *ep; + unsigned char *dnptrs[20], **dpp, **lastdnptr; + uint32_t _res_options; + int n; + + if (!buf || buflen < HFIXEDSZ) { + h_errno = NETDB_INTERNAL; + return -1; + } + + again: + __UCLIBC_MUTEX_LOCK(__resolv_lock); + _res_options = _res.options; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + if (!(_res_options & RES_INIT)) { + res_init(); /* our res_init never fails */ + goto again; + } + +#ifdef DEBUG + if (_res_options & RES_DEBUG) + printf(";; res_mkquery(%d, %s, %d, %d)\n", + op, dname && *dname ? dname : "<null>", class, type); +#endif + + memset(buf, 0, HFIXEDSZ); + hp = (HEADER *) buf; + hp->id = getpid() & 0xffff; + hp->opcode = op; + hp->rd = (_res_options & RES_RECURSE) != 0U; + hp->rcode = NOERROR; + + cp = buf + HFIXEDSZ; + ep = buf + buflen; + dpp = dnptrs; + *dpp++ = buf; + *dpp++ = NULL; + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; + + /* + * perform opcode specific processing + */ + switch (op) { + case QUERY: + case NS_NOTIFY_OP: + if (ep - cp < QFIXEDSZ) + return -1; + + n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs, lastdnptr); + if (n < 0) + return -1; + + cp += n; + NS_PUT16(type, cp); + NS_PUT16(class, cp); + hp->qdcount = htons(1); + + if (op == QUERY || data == NULL) + break; + + /* + * Make an additional record for completion domain. + */ + if ((ep - cp) < RRFIXEDSZ) + return -1; + + n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ, + dnptrs, lastdnptr); + if (n < 0) + return -1; + + cp += n; + NS_PUT16(T_NULL, cp); + NS_PUT16(class, cp); + NS_PUT32(0, cp); + NS_PUT16(0, cp); + hp->arcount = htons(1); + + break; + + case IQUERY: + /* + * Initialize answer section + */ + if (ep - cp < 1 + RRFIXEDSZ + datalen) + return -1; + + *cp++ = '\0'; /*%< no domain name */ + NS_PUT16(type, cp); + NS_PUT16(class, cp); + NS_PUT32(0, cp); + NS_PUT16(datalen, cp); + + if (datalen) { + memcpy(cp, data, (size_t)datalen); + cp += datalen; + } + + hp->ancount = htons(1); + break; + + default: + return -1; + } + + return cp - buf; +} +#endif /* L_res_data */ + +/* Unimplemented: */ +/* res_send */ diff --git a/libc/inet/rpc/Makefile.in b/libc/inet/rpc/Makefile.in index 2f1246b20..9abe85dc8 100644 --- a/libc/inet/rpc/Makefile.in +++ b/libc/inet/rpc/Makefile.in @@ -1,15 +1,16 @@ # Makefile for uClibc # -# Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> +# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org> # # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. # -CFLAGS-rpc := -fno-strict-aliasing +subdirs += libc/inet/rpc + +CFLAGS-y-libc/inet/rpc := -fno-strict-aliasing -ifneq ($(UCLIBC_HAS_FULL_RPC),y) # For now, only compile the stuff needed to do an NFS mount.... -CSRC:= authunix_prot.c auth_none.c auth_unix.c bindresvport.c \ +CSRC_NFS = authunix_prot.c auth_none.c auth_unix.c bindresvport.c \ clnt_perror.c clnt_simple.c clnt_tcp.c clnt_udp.c \ create_xid.c getrpcent.c \ pmap_clnt.c pm_getmaps.c pm_getport.c pmap_prot.c pmap_prot2.c \ @@ -17,29 +18,25 @@ CSRC:= authunix_prot.c auth_none.c auth_unix.c bindresvport.c \ rpc_prot.c rpc_thread.c rtime.c ruserpass.c sa_len.c \ svc.c svc_auth.c svc_authux.c \ xdr.c xdr_array.c xdr_mem.c xdr_rec.c xdr_reference.c -endif INET_RPC_DIR:=$(top_srcdir)libc/inet/rpc INET_RPC_OUT:=$(top_builddir)libc/inet/rpc -ifeq ($(UCLIBC_HAS_FULL_RPC),y) -INET_RPC_SRC:=$(wildcard $(INET_RPC_DIR)/*.c) -else -INET_RPC_SRC:=$(patsubst %.c,$(INET_RPC_DIR)/%.c,$(CSRC)) -endif -# rpc_thread.oS is better, because the header adds unneeded references to __pthread_internal_tsd* -INET_RPC_SRC:=$(filter-out $(INET_RPC_DIR)/rpc_thread.c,$(INET_RPC_SRC)) - -INET_RPC_OBJ:=$(patsubst $(INET_RPC_DIR)/%.c,$(INET_RPC_OUT)/%.o,$(INET_RPC_SRC)) +CSRC_ALL = $(notdir $(wildcard $(INET_RPC_DIR)/*.c)) +CSRC-y := $(if $(UCLIBC_HAS_FULL_RPC),$(CSRC_ALL),$(CSRC_NFS)) +# rpc_thread.oS is better, because the header adds unneeded references +# to __pthread_internal_tsd* +CSRC-y := $(filter-out rpc_thread.c,$(CSRC-y)) -libc-static-$(UCLIBC_HAS_RPC)+=$(INET_RPC_OUT)/rpc_thread.o -libc-shared-$(UCLIBC_HAS_RPC)+=$(INET_RPC_OUT)/rpc_thread.oS +INET_RPC_SRC:=$(patsubst %.c,$(INET_RPC_DIR)/%.c,$(CSRC-y)) +INET_RPC_OBJ:=$(patsubst %.c,$(INET_RPC_OUT)/%.o,$(CSRC-y)) +libc-static-$(UCLIBC_HAS_RPC) += $(INET_RPC_OUT)/rpc_thread.o +libc-shared-$(UCLIBC_HAS_RPC) += $(INET_RPC_OUT)/rpc_thread.oS libc-nomulti-$(UCLIBC_HAS_RPC) += $(INET_RPC_OUT)/rpc_thread.o +libc-$(UCLIBC_HAS_RPC) += $(INET_RPC_OBJ) -libc-$(UCLIBC_HAS_RPC)+=$(INET_RPC_OBJ) - -objclean-y+=inet_rpc_objclean +objclean-y+=CLEAN_libc/inet/rpc -inet_rpc_objclean: - $(RM) $(INET_RPC_OUT)/*.{o,os,oS} +CLEAN_libc/inet/rpc: + $(do_rm) $(addprefix $(INET_RPC_OUT)/*., o os oS) diff --git a/libc/inet/rpc/auth_none.c b/libc/inet/rpc/auth_none.c index 05851025f..4bf37cb10 100644 --- a/libc/inet/rpc/auth_none.c +++ b/libc/inet/rpc/auth_none.c @@ -35,12 +35,8 @@ * credentials and verifiers to remote systems. */ -#define __FORCE_GLIBC -#include <features.h> #include "rpc_private.h" -libc_hidden_proto(xdrmem_create) -libc_hidden_proto(xdr_opaque_auth) #define MAX_MARSHAL_SIZE 20 @@ -68,50 +64,54 @@ struct authnone_private_s { char marshalled_client[MAX_MARSHAL_SIZE]; u_int mcnt; }; + +static struct authnone_private_s authnone_private; #ifdef __UCLIBC_HAS_THREADS__ -#define authnone_private (*(struct authnone_private_s **)&RPC_THREAD_VARIABLE(authnone_private_s)) -#else -static struct authnone_private_s *authnone_private; +__libc_once_define(static, authnone_private_guard); #endif -libc_hidden_proto(authnone_create) -AUTH * -authnone_create (void) +static void authnone_create_once (void); + +static void +authnone_create_once (void) { struct authnone_private_s *ap; XDR xdr_stream; XDR *xdrs; - ap = (struct authnone_private_s *) authnone_private; - if (ap == NULL) - { - ap = (struct authnone_private_s *) calloc (1, sizeof (*ap)); - if (ap == NULL) - return NULL; - authnone_private = ap; - } - if (!ap->mcnt) - { - ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth; - ap->no_client.ah_ops = (struct auth_ops *)&ops; - xdrs = &xdr_stream; - xdrmem_create (xdrs, ap->marshalled_client, (u_int) MAX_MARSHAL_SIZE, - XDR_ENCODE); - (void) xdr_opaque_auth (xdrs, &ap->no_client.ah_cred); - (void) xdr_opaque_auth (xdrs, &ap->no_client.ah_verf); - ap->mcnt = XDR_GETPOS (xdrs); - XDR_DESTROY (xdrs); - } - return (&ap->no_client); + ap = &authnone_private; + + ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth; + ap->no_client.ah_ops = (struct auth_ops *) &ops; + xdrs = &xdr_stream; + xdrmem_create(xdrs, ap->marshalled_client, + (u_int) MAX_MARSHAL_SIZE, XDR_ENCODE); + (void) xdr_opaque_auth(xdrs, &ap->no_client.ah_cred); + (void) xdr_opaque_auth(xdrs, &ap->no_client.ah_verf); + ap->mcnt = XDR_GETPOS (xdrs); + XDR_DESTROY (xdrs); +} + +AUTH * +authnone_create (void) +{ +#ifdef __UCLIBC_HAS_THREADS__ + __libc_once (authnone_private_guard, authnone_create_once); +#else + authnone_create_once(); +#endif + return &authnone_private.no_client; } libc_hidden_def(authnone_create) static bool_t -authnone_marshal (AUTH *client attribute_unused, XDR *xdrs) +authnone_marshal (AUTH *client, XDR *xdrs) { struct authnone_private_s *ap; - ap = authnone_private; + /* authnone_create returned authnone_private->no_client, which is + the first field of struct authnone_private_s. */ + ap = (struct authnone_private_s *) client; if (ap == NULL) return FALSE; return (*xdrs->x_ops->x_putbytes) (xdrs, ap->marshalled_client, ap->mcnt); diff --git a/libc/inet/rpc/auth_unix.c b/libc/inet/rpc/auth_unix.c index 0654b51c1..72d7a7af9 100644 --- a/libc/inet/rpc/auth_unix.c +++ b/libc/inet/rpc/auth_unix.c @@ -38,13 +38,11 @@ * for the credentials. */ -#define __FORCE_GLIBC -#include <features.h> - #include <limits.h> #include <stdio.h> #include <string.h> #include <unistd.h> +#include <libintl.h> #include <sys/param.h> #include <rpc/types.h> @@ -52,27 +50,6 @@ #include <rpc/auth.h> #include <rpc/auth_unix.h> -#ifdef USE_IN_LIBIO -# include <wchar.h> -#endif - -/* Experimentally off - libc_hidden_proto(memcpy) */ -libc_hidden_proto(sysconf) -libc_hidden_proto(getegid) -libc_hidden_proto(geteuid) -libc_hidden_proto(getgroups) -libc_hidden_proto(gethostname) -libc_hidden_proto(xdrmem_create) -libc_hidden_proto(xdr_authunix_parms) -libc_hidden_proto(xdr_opaque_auth) -libc_hidden_proto(gettimeofday) -libc_hidden_proto(fputs) -libc_hidden_proto(perror) -libc_hidden_proto(abort) -#ifdef USE_IN_LIBIO -libc_hidden_proto(fwprintf) -#endif - /* * Unix authenticator operations vector */ @@ -82,7 +59,7 @@ static bool_t authunix_validate (AUTH *, struct opaque_auth *); static bool_t authunix_refresh (AUTH *); static void authunix_destroy (AUTH *); -static struct auth_ops auth_unix_ops = { +static const struct auth_ops auth_unix_ops = { authunix_nextverf, authunix_marshal, authunix_validate, @@ -109,7 +86,6 @@ static bool_t marshal_new_auth (AUTH *) internal_function; * Create a unix style authenticator. * Returns an auth handle with the given stuff in it. */ -libc_hidden_proto(authunix_create) AUTH * authunix_create (char *machname, uid_t uid, gid_t gid, int len, gid_t *aup_gids) @@ -129,13 +105,7 @@ authunix_create (char *machname, uid_t uid, gid_t gid, int len, if (auth == NULL || au == NULL) { no_memory: -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", - _("authunix_create: out of memory\n")); - else -#endif - (void) fputs (_("authunix_create: out of memory\n"), stderr); + (void) fputs (_("authunix_create: out of memory\n"), stderr); mem_free (auth, sizeof (*auth)); mem_free (au, sizeof (*au)); return NULL; @@ -182,7 +152,6 @@ libc_hidden_def(authunix_create) * Returns an auth handle with parameters determined by doing lots of * syscalls. */ -libc_hidden_proto(authunix_create_default) AUTH * authunix_create_default (void) { @@ -345,7 +314,7 @@ marshal_new_auth (AUTH *auth) xdrmem_create (xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); if ((!xdr_opaque_auth (xdrs, &(auth->ah_cred))) || (!xdr_opaque_auth (xdrs, &(auth->ah_verf)))) - perror (_("auth_none.c - Fatal marshalling problem")); + perror (_("auth_unix.c - Fatal marshalling problem")); else au->au_mpos = XDR_GETPOS (xdrs); diff --git a/libc/inet/rpc/authunix_prot.c b/libc/inet/rpc/authunix_prot.c index 62d1cb724..272990056 100644 --- a/libc/inet/rpc/authunix_prot.c +++ b/libc/inet/rpc/authunix_prot.c @@ -39,17 +39,11 @@ #include <rpc/auth.h> #include <rpc/auth_unix.h> -libc_hidden_proto(xdr_string) -libc_hidden_proto(xdr_u_int) -libc_hidden_proto(xdr_array) -libc_hidden_proto(xdr_u_long) -libc_hidden_proto(xdr_u_short) /* * XDR for unix authentication parameters. * Unfortunately, none of these can be declared const. */ -libc_hidden_proto(xdr_authunix_parms) bool_t xdr_authunix_parms (XDR * xdrs, struct authunix_parms *p) { diff --git a/libc/inet/rpc/bindresvport.c b/libc/inet/rpc/bindresvport.c index 3f266e6cc..30bbd2684 100644 --- a/libc/inet/rpc/bindresvport.c +++ b/libc/inet/rpc/bindresvport.c @@ -30,9 +30,6 @@ * Copyright (c) 1987 by Sun Microsystems, Inc. */ -#define __FORCE_GLIBC -#include <features.h> - #include <errno.h> #include <unistd.h> #include <string.h> @@ -40,14 +37,10 @@ #include <sys/socket.h> #include <netinet/in.h> -/* Experimentally off - libc_hidden_proto(memset) */ -libc_hidden_proto(bind) -libc_hidden_proto(getpid) /* * Bind a socket to a privileged IP port */ -libc_hidden_proto(bindresvport) int bindresvport (int sd, struct sockaddr_in *sin) { diff --git a/libc/inet/rpc/clnt_generic.c b/libc/inet/rpc/clnt_generic.c index 54bd0e914..f2d6c1295 100644 --- a/libc/inet/rpc/clnt_generic.c +++ b/libc/inet/rpc/clnt_generic.c @@ -30,9 +30,6 @@ * Copyright (C) 1987, Sun Microsystems, Inc. */ -#define __FORCE_GLIBC -#include <features.h> - #include <alloca.h> #include <errno.h> #include <string.h> @@ -40,16 +37,6 @@ #include <sys/socket.h> #include <netdb.h> -/* Experimentally off - libc_hidden_proto(memcpy) */ -/* Experimentally off - libc_hidden_proto(memset) */ -/* Experimentally off - libc_hidden_proto(strcmp) */ -/* Experimentally off - libc_hidden_proto(strcpy) */ -libc_hidden_proto(clnttcp_create) -libc_hidden_proto(clntudp_create) -libc_hidden_proto(clntunix_create) -libc_hidden_proto(getprotobyname_r) -libc_hidden_proto(gethostbyname_r) -libc_hidden_proto(__rpc_thread_createerr) /* * Generic client creation: takes (hostname, program-number, protocol) and @@ -129,7 +116,7 @@ clnt_create (const char *hostname, u_long prog, u_long vers, prttmpbuf = alloca (prtbuflen); while (getprotobyname_r (proto, &protobuf, prttmpbuf, prtbuflen, &p) != 0 || p == NULL) - if (errno != ERANGE) + if (errno != ERANGE) { struct rpc_createerr *ce = &get_rpc_createerr (); ce->cf_stat = RPC_UNKNOWNPROTO; diff --git a/libc/inet/rpc/clnt_perror.c b/libc/inet/rpc/clnt_perror.c index 7e6c907ce..190e07eb7 100644 --- a/libc/inet/rpc/clnt_perror.c +++ b/libc/inet/rpc/clnt_perror.c @@ -38,28 +38,10 @@ static char sccsid[] = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro"; * */ -#define __FORCE_GLIBC -#include <features.h> - #include <stdio.h> #include <string.h> #include "rpc_private.h" -#ifdef USE_IN_LIBIO -# include <wchar.h> -# include <libio/iolibio.h> -# define fputs(s, f) _IO_fputs (s, f) -#endif - -/* Experimentally off - libc_hidden_proto(strcpy) */ -/* Experimentally off - libc_hidden_proto(strlen) */ -libc_hidden_proto(sprintf) -libc_hidden_proto(__glibc_strerror_r) -libc_hidden_proto(fputs) -#ifdef USE_IN_LIBIO -libc_hidden_proto(fwprintf) -#endif - static char *auth_errmsg (enum auth_stat stat) internal_function; #ifdef __UCLIBC_HAS_THREADS__ @@ -90,74 +72,74 @@ struct rpc_errtab static const char rpc_errstr[] = { #define RPC_SUCCESS_IDX 0 - _("RPC: Success") + N_("RPC: Success") "\0" #define RPC_CANTENCODEARGS_IDX (RPC_SUCCESS_IDX + sizeof "RPC: Success") - _("RPC: Can't encode arguments") + N_("RPC: Can't encode arguments") "\0" #define RPC_CANTDECODERES_IDX (RPC_CANTENCODEARGS_IDX \ + sizeof "RPC: Can't encode arguments") - _("RPC: Can't decode result") + N_("RPC: Can't decode result") "\0" #define RPC_CANTSEND_IDX (RPC_CANTDECODERES_IDX \ + sizeof "RPC: Can't decode result") - _("RPC: Unable to send") + N_("RPC: Unable to send") "\0" #define RPC_CANTRECV_IDX (RPC_CANTSEND_IDX \ + sizeof "RPC: Unable to send") - _("RPC: Unable to receive") + N_("RPC: Unable to receive") "\0" #define RPC_TIMEDOUT_IDX (RPC_CANTRECV_IDX \ + sizeof "RPC: Unable to receive") - _("RPC: Timed out") + N_("RPC: Timed out") "\0" #define RPC_VERSMISMATCH_IDX (RPC_TIMEDOUT_IDX \ + sizeof "RPC: Timed out") - _("RPC: Incompatible versions of RPC") + N_("RPC: Incompatible versions of RPC") "\0" #define RPC_AUTHERROR_IDX (RPC_VERSMISMATCH_IDX \ + sizeof "RPC: Incompatible versions of RPC") - _("RPC: Authentication error") + N_("RPC: Authentication error") "\0" #define RPC_PROGUNAVAIL_IDX (RPC_AUTHERROR_IDX \ + sizeof "RPC: Authentication error") - _("RPC: Program unavailable") + N_("RPC: Program unavailable") "\0" #define RPC_PROGVERSMISMATCH_IDX (RPC_PROGUNAVAIL_IDX \ + sizeof "RPC: Program unavailable") - _("RPC: Program/version mismatch") + N_("RPC: Program/version mismatch") "\0" #define RPC_PROCUNAVAIL_IDX (RPC_PROGVERSMISMATCH_IDX \ + sizeof "RPC: Program/version mismatch") - _("RPC: Procedure unavailable") + N_("RPC: Procedure unavailable") "\0" #define RPC_CANTDECODEARGS_IDX (RPC_PROCUNAVAIL_IDX \ + sizeof "RPC: Procedure unavailable") - _("RPC: Server can't decode arguments") + N_("RPC: Server can't decode arguments") "\0" #define RPC_SYSTEMERROR_IDX (RPC_CANTDECODEARGS_IDX \ + sizeof "RPC: Server can't decode arguments") - _("RPC: Remote system error") + N_("RPC: Remote system error") "\0" #define RPC_UNKNOWNHOST_IDX (RPC_SYSTEMERROR_IDX \ + sizeof "RPC: Remote system error") - _("RPC: Unknown host") + N_("RPC: Unknown host") "\0" #define RPC_UNKNOWNPROTO_IDX (RPC_UNKNOWNHOST_IDX \ + sizeof "RPC: Unknown host") - _("RPC: Unknown protocol") + N_("RPC: Unknown protocol") "\0" #define RPC_PMAPFAILURE_IDX (RPC_UNKNOWNPROTO_IDX \ + sizeof "RPC: Unknown protocol") - _("RPC: Port mapper failure") + N_("RPC: Port mapper failure") "\0" #define RPC_PROGNOTREGISTERED_IDX (RPC_PMAPFAILURE_IDX \ + sizeof "RPC: Port mapper failure") - _("RPC: Program not registered") + N_("RPC: Program not registered") "\0" #define RPC_FAILED_IDX (RPC_PROGNOTREGISTERED_IDX \ + sizeof "RPC: Program not registered") - _("RPC: Failed (unspecified error)") + N_("RPC: Failed (unspecified error)") }; static const struct rpc_errtab rpc_errlist[] = @@ -186,7 +168,6 @@ static const struct rpc_errtab rpc_errlist[] = /* * This interface for use by clntrpc */ -libc_hidden_proto(clnt_sperrno) char * clnt_sperrno (enum clnt_stat stat) { @@ -199,25 +180,19 @@ clnt_sperrno (enum clnt_stat stat) return (char*)_(rpc_errstr + rpc_errlist[i].message_off); } } - return _("RPC: (unknown error code)"); + return N_("RPC: (unknown error code)"); } libc_hidden_def(clnt_sperrno) void clnt_perrno (enum clnt_stat num) { -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", clnt_sperrno (num)); - else -#endif - (void) fputs (clnt_sperrno (num), stderr); + (void) fputs (clnt_sperrno (num), stderr); } /* * Print reply error info */ -libc_hidden_proto(clnt_sperror) char * clnt_sperror (CLIENT * rpch, const char *msg) { @@ -303,20 +278,13 @@ clnt_sperror (CLIENT * rpch, const char *msg) } libc_hidden_def(clnt_sperror) -libc_hidden_proto(clnt_perror) void clnt_perror (CLIENT * rpch, const char *msg) { -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", clnt_sperror (rpch, msg)); - else -#endif - (void) fputs (clnt_sperror (rpch, msg), stderr); + (void) fputs (clnt_sperror (rpch, msg), stderr); } libc_hidden_def(clnt_perror) -libc_hidden_proto(clnt_spcreateerror) char * clnt_spcreateerror (const char *msg) { @@ -365,12 +333,7 @@ libc_hidden_def(clnt_spcreateerror) void clnt_pcreateerror (const char *msg) { -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", clnt_spcreateerror (msg)); - else -#endif - (void) fputs (clnt_spcreateerror (msg), stderr); + (void) fputs (clnt_spcreateerror (msg), stderr); } struct auth_errtab @@ -382,34 +345,34 @@ struct auth_errtab static const char auth_errstr[] = { #define AUTH_OK_IDX 0 - _("Authentication OK") + N_("Authentication OK") "\0" #define AUTH_BADCRED_IDX (AUTH_OK_IDX + sizeof "Authentication OK") - _("Invalid client credential") + N_("Invalid client credential") "\0" #define AUTH_REJECTEDCRED_IDX (AUTH_BADCRED_IDX \ + sizeof "Invalid client credential") - _("Server rejected credential") + N_("Server rejected credential") "\0" #define AUTH_BADVERF_IDX (AUTH_REJECTEDCRED_IDX \ + sizeof "Server rejected credential") - _("Invalid client verifier") + N_("Invalid client verifier") "\0" #define AUTH_REJECTEDVERF_IDX (AUTH_BADVERF_IDX \ + sizeof "Invalid client verifier") - _("Server rejected verifier") + N_("Server rejected verifier") "\0" #define AUTH_TOOWEAK_IDX (AUTH_REJECTEDVERF_IDX \ + sizeof "Server rejected verifier") - _("Client credential too weak") + N_("Client credential too weak") "\0" #define AUTH_INVALIDRESP_IDX (AUTH_TOOWEAK_IDX \ + sizeof "Client credential too weak") - _("Invalid server verifier") + N_("Invalid server verifier") "\0" #define AUTH_FAILED_IDX (AUTH_INVALIDRESP_IDX \ + sizeof "Invalid server verifier") - _("Failed (unspecified error)") + N_("Failed (unspecified error)") }; static const struct auth_errtab auth_errlist[] = diff --git a/libc/inet/rpc/clnt_raw.c b/libc/inet/rpc/clnt_raw.c index b44bd38b8..ddc1c1421 100644 --- a/libc/inet/rpc/clnt_raw.c +++ b/libc/inet/rpc/clnt_raw.c @@ -42,20 +42,11 @@ static char sccsid[] = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro"; * any interference from the kernel. */ -#define __FORCE_GLIBC #include <features.h> #include "rpc_private.h" #include <rpc/svc.h> #include <rpc/xdr.h> -libc_hidden_proto(perror) -libc_hidden_proto(authnone_create) -libc_hidden_proto(xdrmem_create) -libc_hidden_proto(xdr_callhdr) -libc_hidden_proto(xdr_replymsg) -libc_hidden_proto(xdr_opaque_auth) -libc_hidden_proto(svc_getreq) -libc_hidden_proto(_seterr_reply) #define MCALL_MSG_SIZE 24 @@ -84,7 +75,7 @@ static bool_t clntraw_freeres (CLIENT *, xdrproc_t, caddr_t); static bool_t clntraw_control (CLIENT *, int, char *); static void clntraw_destroy (CLIENT *); -static struct clnt_ops client_ops = +static const struct clnt_ops client_ops = { clntraw_call, clntraw_abort, @@ -141,14 +132,9 @@ clntraw_create (u_long prog, u_long vers) } static enum clnt_stat -clntraw_call (h, proc, xargs, argsp, xresults, resultsp, timeout) - CLIENT *h; - u_long proc; - xdrproc_t xargs; - caddr_t argsp; - xdrproc_t xresults; - caddr_t resultsp; - struct timeval timeout attribute_unused; +clntraw_call (CLIENT *h, u_long proc, xdrproc_t xargs, caddr_t argsp, + xdrproc_t xresults, caddr_t resultsp, + struct timeval timeout attribute_unused) { struct clntraw_private_s *clp = clntraw_private; XDR *xdrs = &clp->xdr_stream; diff --git a/libc/inet/rpc/clnt_simple.c b/libc/inet/rpc/clnt_simple.c index 745a50213..d67e69527 100644 --- a/libc/inet/rpc/clnt_simple.c +++ b/libc/inet/rpc/clnt_simple.c @@ -38,9 +38,6 @@ static char sccsid[] = "@(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro"; * Copyright (C) 1984, Sun Microsystems, Inc. */ -#define __FORCE_GLIBC -#include <features.h> - #include <alloca.h> #include <errno.h> #include <stdio.h> @@ -50,12 +47,6 @@ static char sccsid[] = "@(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro"; #include <netdb.h> #include <string.h> -/* Experimentally off - libc_hidden_proto(memcpy) */ -/* Experimentally off - libc_hidden_proto(strcmp) */ -/* Experimentally off - libc_hidden_proto(strncpy) */ -libc_hidden_proto(close) -libc_hidden_proto(clntudp_create) -libc_hidden_proto(gethostbyname_r) struct callrpc_private_s { diff --git a/libc/inet/rpc/clnt_tcp.c b/libc/inet/rpc/clnt_tcp.c index 23e4ca863..4b19a9aab 100644 --- a/libc/inet/rpc/clnt_tcp.c +++ b/libc/inet/rpc/clnt_tcp.c @@ -50,46 +50,14 @@ static char sccsid[] = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro"; * Now go hang yourself. */ -#define __FORCE_GLIBC -#include <features.h> - #include <netdb.h> #include <errno.h> #include <stdio.h> #include <unistd.h> -#include <rpc/rpc.h> +#include "rpc_private.h" #include <sys/poll.h> #include <sys/socket.h> #include <rpc/pmap_clnt.h> -#ifdef USE_IN_LIBIO -# include <wchar.h> -#endif - -libc_hidden_proto(socket) -libc_hidden_proto(read) -libc_hidden_proto(write) -libc_hidden_proto(close) -libc_hidden_proto(authnone_create) -libc_hidden_proto(xdrrec_create) -libc_hidden_proto(xdrrec_endofrecord) -libc_hidden_proto(xdrrec_skiprecord) -libc_hidden_proto(xdr_callhdr) -libc_hidden_proto(xdr_replymsg) -libc_hidden_proto(xdr_opaque_auth) -libc_hidden_proto(xdrmem_create) -libc_hidden_proto(xdr_void) -libc_hidden_proto(pmap_getport) -libc_hidden_proto(_seterr_reply) -libc_hidden_proto(connect) -libc_hidden_proto(bindresvport) -libc_hidden_proto(poll) -libc_hidden_proto(fputs) -libc_hidden_proto(__rpc_thread_createerr) -#ifdef USE_IN_LIBIO -libc_hidden_proto(fwprintf) -#endif - -extern u_long _create_xid (void) attribute_hidden; #define MCALL_MSG_SIZE 24 @@ -117,7 +85,7 @@ static bool_t clnttcp_freeres (CLIENT *, xdrproc_t, caddr_t); static bool_t clnttcp_control (CLIENT *, int, char *); static void clnttcp_destroy (CLIENT *); -static struct clnt_ops tcp_ops = +static const struct clnt_ops tcp_ops = { clnttcp_call, clnttcp_abort, @@ -141,7 +109,6 @@ static struct clnt_ops tcp_ops = * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this * something more useful. */ -libc_hidden_proto(clnttcp_create) CLIENT * clnttcp_create (struct sockaddr_in *raddr, u_long prog, u_long vers, int *sockp, u_int sendsz, u_int recvsz) @@ -155,13 +122,7 @@ clnttcp_create (struct sockaddr_in *raddr, u_long prog, u_long vers, if (h == NULL || ct == NULL) { struct rpc_createerr *ce = &get_rpc_createerr (); -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", - _("clnttcp_create: out of memory\n")); - else -#endif - (void) fputs (_("clnttcp_create: out of memory\n"), stderr); + (void) fputs (_("clnttcp_create: out of memory\n"), stderr); ce->cf_stat = RPC_SYSTEMERROR; ce->cf_error.re_errno = ENOMEM; goto fooy; @@ -262,14 +223,9 @@ fooy: libc_hidden_def(clnttcp_create) static enum clnt_stat -clnttcp_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout) - CLIENT *h; - u_long proc; - xdrproc_t xdr_args; - caddr_t args_ptr; - xdrproc_t xdr_results; - caddr_t results_ptr; - struct timeval timeout; +clnttcp_call (CLIENT *h, u_long proc, xdrproc_t xdr_args, caddr_t args_ptr, + xdrproc_t xdr_results, caddr_t results_ptr, + struct timeval timeout) { struct ct_data *ct = (struct ct_data *) h->cl_private; XDR *xdrs = &(ct->ct_xdrs); @@ -370,9 +326,7 @@ call_again: } static void -clnttcp_geterr (h, errp) - CLIENT *h; - struct rpc_err *errp; +clnttcp_geterr (CLIENT *h, struct rpc_err *errp) { struct ct_data *ct = (struct ct_data *) h->cl_private; @@ -381,10 +335,7 @@ clnttcp_geterr (h, errp) } static bool_t -clnttcp_freeres (cl, xdr_res, res_ptr) - CLIENT *cl; - xdrproc_t xdr_res; - caddr_t res_ptr; +clnttcp_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) { struct ct_data *ct = (struct ct_data *) cl->cl_private; XDR *xdrs = &(ct->ct_xdrs); @@ -394,7 +345,7 @@ clnttcp_freeres (cl, xdr_res, res_ptr) } static void -clnttcp_abort () +clnttcp_abort (void) { } @@ -437,6 +388,7 @@ clnttcp_control (CLIENT *cl, int request, char *info) /* This will set the xid of the NEXT call */ *(u_long *)ct->ct_mcall = htonl (*(u_long *)info - 1); /* decrement by 1 as clnttcp_call() increments once */ + break; case CLGET_VERS: /* * This RELIES on the information that, in the call body, diff --git a/libc/inet/rpc/clnt_udp.c b/libc/inet/rpc/clnt_udp.c index 1d7cb4863..4fc55b732 100644 --- a/libc/inet/rpc/clnt_udp.c +++ b/libc/inet/rpc/clnt_udp.c @@ -37,12 +37,9 @@ static char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro"; * Copyright (C) 1984, Sun Microsystems, Inc. */ -#define __FORCE_GLIBC -#include <features.h> - #include <stdio.h> #include <unistd.h> -#include <rpc/rpc.h> +#include "rpc_private.h" #include <rpc/xdr.h> #include <rpc/clnt.h> #include <sys/poll.h> @@ -52,41 +49,12 @@ static char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro"; #include <errno.h> #include <rpc/pmap_clnt.h> #include <net/if.h> -#ifdef USE_IN_LIBIO -# include <wchar.h> -libc_hidden_proto(fwprintf) -#endif #ifdef IP_RECVERR #include "errqueue.h" #include <sys/uio.h> #endif -/* Experimentally off - libc_hidden_proto(memcmp) */ -libc_hidden_proto(ioctl) -libc_hidden_proto(socket) -libc_hidden_proto(close) -/* CMSG_NXTHDR is using it */ -libc_hidden_proto(__cmsg_nxthdr) - -libc_hidden_proto(authnone_create) -libc_hidden_proto(xdrmem_create) -libc_hidden_proto(xdr_callhdr) -libc_hidden_proto(xdr_replymsg) -libc_hidden_proto(xdr_opaque_auth) -libc_hidden_proto(pmap_getport) -libc_hidden_proto(_seterr_reply) -libc_hidden_proto(setsockopt) -libc_hidden_proto(bindresvport) -libc_hidden_proto(recvfrom) -libc_hidden_proto(sendto) -libc_hidden_proto(recvmsg) -libc_hidden_proto(poll) -libc_hidden_proto(fputs) -libc_hidden_proto(__rpc_thread_createerr) - -extern u_long _create_xid (void) attribute_hidden; - /* * UDP bases client side rpc operations */ @@ -98,7 +66,7 @@ static bool_t clntudp_freeres (CLIENT *, xdrproc_t, caddr_t); static bool_t clntudp_control (CLIENT *, int, char *); static void clntudp_destroy (CLIENT *); -static struct clnt_ops udp_ops = +static const struct clnt_ops udp_ops = { clntudp_call, clntudp_abort, @@ -137,17 +105,16 @@ struct cu_data * NB: The rpch->cl_auth is initialized to null authentication. * Caller may wish to set this something more useful. * - * wait is the amount of time used between retransmitting a call if + * _wait is the amount of time used between retransmitting a call if * no response has been heard; retransmission occurs until the actual * rpc call times out. * * sendsz and recvsz are the maximum allowable packet sizes that can be * sent and received. */ -libc_hidden_proto(clntudp_bufcreate) CLIENT * clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version, - struct timeval wait, int *sockp, u_int sendsz, + struct timeval _wait, int *sockp, u_int sendsz, u_int recvsz) { CLIENT *cl; @@ -161,13 +128,7 @@ clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version, if (cl == NULL || cu == NULL) { struct rpc_createerr *ce = &get_rpc_createerr (); -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", - _("clntudp_create: out of memory\n")); - else -#endif - (void) fputs (_("clntudp_create: out of memory\n"), stderr); + (void) fputs (_("clntudp_create: out of memory\n"), stderr); ce->cf_stat = RPC_SYSTEMERROR; ce->cf_error.re_errno = ENOMEM; goto fooy; @@ -188,7 +149,7 @@ clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version, cl->cl_private = (caddr_t) cu; cu->cu_raddr = *raddr; cu->cu_rlen = sizeof (cu->cu_raddr); - cu->cu_wait = wait; + cu->cu_wait = _wait; cu->cu_total.tv_sec = -1; cu->cu_total.tv_usec = -1; cu->cu_sendsz = sendsz; @@ -245,12 +206,11 @@ fooy: } libc_hidden_def(clntudp_bufcreate) -libc_hidden_proto(clntudp_create) CLIENT * -clntudp_create (struct sockaddr_in *raddr, u_long program, u_long version, struct timeval wait, int *sockp) +clntudp_create (struct sockaddr_in *raddr, u_long program, u_long version, struct timeval _wait, int *sockp) { - return clntudp_bufcreate (raddr, program, version, wait, sockp, + return clntudp_bufcreate (raddr, program, version, _wait, sockp, UDPMSGSIZE, UDPMSGSIZE); } libc_hidden_def(clntudp_create) @@ -283,14 +243,14 @@ is_network_up (int sock) } static enum clnt_stat -clntudp_call (cl, proc, xargs, argsp, xresults, resultsp, utimeout) - CLIENT *cl; /* client handle */ - u_long proc; /* procedure number */ - xdrproc_t xargs; /* xdr routine for args */ - caddr_t argsp; /* pointer to args */ - xdrproc_t xresults; /* xdr routine for results */ - caddr_t resultsp; /* pointer to results */ - struct timeval utimeout; /* seconds to wait before giving up */ +clntudp_call ( + CLIENT *cl, /* client handle */ + u_long proc, /* procedure number */ + xdrproc_t xargs, /* xdr routine for args */ + caddr_t argsp, /* pointer to args */ + xdrproc_t xresults, /* xdr routine for results */ + caddr_t resultsp, /* pointer to results */ + struct timeval utimeout /* seconds to wait before giving up */) { struct cu_data *cu = (struct cu_data *) cl->cl_private; XDR *xdrs; @@ -577,6 +537,7 @@ clntudp_control (CLIENT *cl, int request, char *info) /* This will set the xid of the NEXT call */ *(u_long *)cu->cu_outbuf = htonl(*(u_long *)info - 1); /* decrement by 1 as clntudp_call() increments once */ + break; case CLGET_VERS: /* * This RELIES on the information that, in the call body, diff --git a/libc/inet/rpc/clnt_unix.c b/libc/inet/rpc/clnt_unix.c index 73be74288..e4a6672b7 100644 --- a/libc/inet/rpc/clnt_unix.c +++ b/libc/inet/rpc/clnt_unix.c @@ -46,49 +46,15 @@ * Now go hang yourself. */ -#define __FORCE_GLIBC -#include <features.h> - #include <netdb.h> #include <errno.h> #include <stdio.h> #include <unistd.h> -#include <rpc/rpc.h> +#include "rpc_private.h" #include <sys/uio.h> #include <sys/poll.h> #include <sys/socket.h> #include <rpc/pmap_clnt.h> -#ifdef USE_IN_LIBIO -# include <wchar.h> -libc_hidden_proto(fwprintf) -#endif - -/* Experimentally off - libc_hidden_proto(strlen) */ -/* Experimentally off - libc_hidden_proto(memcpy) */ -libc_hidden_proto(socket) -libc_hidden_proto(close) -libc_hidden_proto(getpid) -libc_hidden_proto(authnone_create) -libc_hidden_proto(xdrrec_create) -libc_hidden_proto(xdrrec_endofrecord) -libc_hidden_proto(xdrrec_skiprecord) -libc_hidden_proto(xdr_callhdr) -libc_hidden_proto(xdr_replymsg) -libc_hidden_proto(xdr_opaque_auth) -libc_hidden_proto(xdrmem_create) -libc_hidden_proto(xdr_void) -libc_hidden_proto(getegid) -libc_hidden_proto(geteuid) -libc_hidden_proto(_seterr_reply) -libc_hidden_proto(setsockopt) -libc_hidden_proto(connect) -libc_hidden_proto(recvmsg) -libc_hidden_proto(sendmsg) -libc_hidden_proto(poll) -libc_hidden_proto(fputs) -libc_hidden_proto(__rpc_thread_createerr) - -extern u_long _create_xid (void) attribute_hidden; #define MCALL_MSG_SIZE 24 @@ -116,7 +82,7 @@ static bool_t clntunix_freeres (CLIENT *, xdrproc_t, caddr_t); static bool_t clntunix_control (CLIENT *, int, char *); static void clntunix_destroy (CLIENT *); -static struct clnt_ops unix_ops = +static const struct clnt_ops unix_ops = { clntunix_call, clntunix_abort, @@ -140,7 +106,6 @@ static struct clnt_ops unix_ops = * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this * something more useful. */ -libc_hidden_proto(clntunix_create) CLIENT * clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers, int *sockp, u_int sendsz, u_int recvsz) @@ -154,13 +119,7 @@ clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers, if (h == NULL || ct == NULL) { struct rpc_createerr *ce = &get_rpc_createerr (); -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", - _("clntunix_create: out of memory\n")); - else -#endif - (void) fputs (_("clntunix_create: out of memory\n"), stderr); + (void) fputs (_("clntunix_create: out of memory\n"), stderr); ce->cf_stat = RPC_SYSTEMERROR; ce->cf_error.re_errno = ENOMEM; goto fooy; @@ -242,14 +201,9 @@ fooy: libc_hidden_def(clntunix_create) static enum clnt_stat -clntunix_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout) - CLIENT *h; - u_long proc; - xdrproc_t xdr_args; - caddr_t args_ptr; - xdrproc_t xdr_results; - caddr_t results_ptr; - struct timeval timeout; +clntunix_call (CLIENT *h, u_long proc, xdrproc_t xdr_args, caddr_t args_ptr, + xdrproc_t xdr_results, caddr_t results_ptr, + struct timeval timeout) { struct ct_data *ct = (struct ct_data *) h->cl_private; XDR *xdrs = &(ct->ct_xdrs); @@ -356,10 +310,7 @@ clntunix_geterr (CLIENT *h, struct rpc_err *errp) } static bool_t -clntunix_freeres (cl, xdr_res, res_ptr) - CLIENT *cl; - xdrproc_t xdr_res; - caddr_t res_ptr; +clntunix_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) { struct ct_data *ct = (struct ct_data *) cl->cl_private; XDR *xdrs = &(ct->ct_xdrs); @@ -369,7 +320,7 @@ clntunix_freeres (cl, xdr_res, res_ptr) } static void -clntunix_abort () +clntunix_abort (void) { } @@ -411,6 +362,7 @@ clntunix_control (CLIENT *cl, int request, char *info) /* This will set the xid of the NEXT call */ *(u_long *) ct->ct_mcall = htonl (*(u_long *)info - 1); /* decrement by 1 as clntunix_call() increments once */ + break; case CLGET_VERS: /* * This RELIES on the information that, in the call body, @@ -474,7 +426,7 @@ __msgread (int sock, void *data, size_t cnt) struct iovec iov; struct msghdr msg; #ifdef SCM_CREDENTIALS - static char cm[CMSG_SPACE(sizeof (struct ucred))]; + /*static -why??*/ char cm[CMSG_SPACE(sizeof (struct ucred))]; #endif int len; diff --git a/libc/inet/rpc/create_xid.c b/libc/inet/rpc/create_xid.c index e3ee4799b..61487c6a4 100644 --- a/libc/inet/rpc/create_xid.c +++ b/libc/inet/rpc/create_xid.c @@ -13,35 +13,26 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#define __FORCE_GLIBC -#include <features.h> + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <unistd.h> #include <stdlib.h> #include <sys/time.h> -#include <rpc/rpc.h> +#include "rpc_private.h" -libc_hidden_proto(lrand48_r) -libc_hidden_proto(srand48_r) -libc_hidden_proto(gettimeofday) /* The RPC code is not threadsafe, but new code should be threadsafe. */ #include <bits/uClibc_mutex.h> __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); - static smallint is_initialized; static struct drand48_data __rpc_lrand48_data; -u_long _create_xid (void) attribute_hidden; u_long _create_xid (void) { - unsigned long res; + long res; __UCLIBC_MUTEX_LOCK(mylock); diff --git a/libc/inet/rpc/errqueue.h b/libc/inet/rpc/errqueue.h index 9ed6dc62b..07f65e1db 100644 --- a/libc/inet/rpc/errqueue.h +++ b/libc/inet/rpc/errqueue.h @@ -12,9 +12,8 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ /* Linux version. */ diff --git a/libc/inet/rpc/get_myaddress.c b/libc/inet/rpc/get_myaddress.c index a6ba07811..04999a199 100644 --- a/libc/inet/rpc/get_myaddress.c +++ b/libc/inet/rpc/get_myaddress.c @@ -44,17 +44,13 @@ static char sccsid[] = "@(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro"; #include <sys/socket.h> #include <stdio.h> #include <unistd.h> +#include <libintl.h> #include <net/if.h> #include <sys/ioctl.h> /* Order of following two #includes reversed by roland@gnu */ #include <netinet/in.h> #include <arpa/inet.h> -libc_hidden_proto(ioctl) -libc_hidden_proto(socket) -libc_hidden_proto(close) -libc_hidden_proto(perror) -libc_hidden_proto(exit) /* * don't use gethostbyname, which would invoke yellow pages diff --git a/libc/inet/rpc/getrpcent.c b/libc/inet/rpc/getrpcent.c index 186bd130f..dba2a6878 100644 --- a/libc/inet/rpc/getrpcent.c +++ b/libc/inet/rpc/getrpcent.c @@ -33,8 +33,6 @@ * Copyright (c) 1985 by Sun Microsystems, Inc. */ -#define __FORCE_GLIBC -#include <features.h> #include <stdio.h> #include <string.h> #include <sys/types.h> @@ -44,16 +42,6 @@ #include <arpa/inet.h> #include <errno.h> -/* Experimentally off - libc_hidden_proto(memcpy) */ -/* Experimentally off - libc_hidden_proto(memset) */ -/* Experimentally off - libc_hidden_proto(strchr) */ -/* Experimentally off - libc_hidden_proto(strcmp) */ -/* Experimentally off - libc_hidden_proto(strlen) */ -libc_hidden_proto(fopen) -libc_hidden_proto(fclose) -libc_hidden_proto(atoi) -libc_hidden_proto(rewind) -libc_hidden_proto(fgets) /* * Internet version. @@ -70,7 +58,7 @@ static struct rpcdata { char *domain; } *rpcdata; -static char RPCDB[] = "/etc/rpc"; +static const char RPCDB[] = "/etc/rpc"; static struct rpcdata *_rpcdata(void) { @@ -84,7 +72,6 @@ static struct rpcdata *_rpcdata(void) return d; } -libc_hidden_proto(endrpcent) void endrpcent(void) { register struct rpcdata *d = _rpcdata(); @@ -102,7 +89,6 @@ void endrpcent(void) } libc_hidden_def(endrpcent) -libc_hidden_proto(setrpcent) void setrpcent(int f) { register struct rpcdata *d = _rpcdata(); @@ -128,7 +114,6 @@ static struct rpcent *__get_next_rpcent(struct rpcdata *d) return interpret(d); } -libc_hidden_proto(getrpcent) struct rpcent *getrpcent(void) { register struct rpcdata *d = _rpcdata(); @@ -141,7 +126,6 @@ struct rpcent *getrpcent(void) } libc_hidden_def(getrpcent) -libc_hidden_proto(getrpcbynumber) struct rpcent *getrpcbynumber(register int number) { register struct rpcdata *d = _rpcdata(); @@ -159,7 +143,6 @@ struct rpcent *getrpcbynumber(register int number) } libc_hidden_def(getrpcbynumber) -libc_hidden_proto(getrpcbyname) struct rpcent *getrpcbyname(const char *name) { struct rpcent *rpc; diff --git a/libc/inet/rpc/getrpcport.c b/libc/inet/rpc/getrpcport.c index 0a57d1da9..84f1e5ff5 100644 --- a/libc/inet/rpc/getrpcport.c +++ b/libc/inet/rpc/getrpcport.c @@ -35,9 +35,6 @@ static char sccsid[] = "@(#)getrpcport.c 1.3 87/08/11 SMI"; * Copyright (c) 1985 by Sun Microsystems, Inc. */ -#define __FORCE_GLIBC -#include <features.h> - #include <alloca.h> #include <errno.h> #include <stdio.h> @@ -48,9 +45,6 @@ static char sccsid[] = "@(#)getrpcport.c 1.3 87/08/11 SMI"; #include <rpc/pmap_clnt.h> #include <sys/socket.h> -/* Experimentally off - libc_hidden_proto(memcpy) */ -libc_hidden_proto(pmap_getport) -libc_hidden_proto(gethostbyname_r) int getrpcport (const char *host, u_long prognum, u_long versnum, u_int proto) diff --git a/libc/inet/rpc/pm_getmaps.c b/libc/inet/rpc/pm_getmaps.c index 1760adf37..910625a75 100644 --- a/libc/inet/rpc/pm_getmaps.c +++ b/libc/inet/rpc/pm_getmaps.c @@ -39,7 +39,7 @@ static char sccsid[] = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro"; * Copyright (C) 1984, Sun Microsystems, Inc. */ -#include <rpc/rpc.h> +#include "rpc_private.h" #include <rpc/pmap_prot.h> #include <rpc/pmap_clnt.h> #include <netdb.h> @@ -48,11 +48,6 @@ static char sccsid[] = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro"; #include <errno.h> #include <unistd.h> -libc_hidden_proto(clnt_perror) -libc_hidden_proto(clnttcp_create) -libc_hidden_proto(xdr_pmap) -libc_hidden_proto(xdr_pmaplist) -libc_hidden_proto(xdr_void) /* * Get a copy of the current port maps. @@ -83,7 +78,7 @@ pmap_getmaps (struct sockaddr_in *address) } CLNT_DESTROY (client); } - /* (void)__close(_socket); CLNT_DESTROY already closed it */ + /* (void)close(_socket); CLNT_DESTROY already closed it */ address->sin_port = 0; return head; } diff --git a/libc/inet/rpc/pm_getport.c b/libc/inet/rpc/pm_getport.c index 327fb9101..9a0e79178 100644 --- a/libc/inet/rpc/pm_getport.c +++ b/libc/inet/rpc/pm_getport.c @@ -44,10 +44,6 @@ static char sccsid[] = "@(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro"; #include <rpc/pmap_prot.h> #include <rpc/pmap_clnt.h> -libc_hidden_proto(clntudp_bufcreate) -libc_hidden_proto(__rpc_thread_createerr) -libc_hidden_proto(xdr_u_short) -libc_hidden_proto(xdr_pmap) static const struct timeval timeout = {5, 0}; @@ -59,13 +55,9 @@ static const struct timeval tottimeout = * Calls the pmap service remotely to do the lookup. * Returns 0 if no map exists. */ -libc_hidden_proto(pmap_getport) u_short -pmap_getport (address, program, version, protocol) - struct sockaddr_in *address; - u_long program; - u_long version; - u_int protocol; +pmap_getport (struct sockaddr_in *address, u_long program, u_long version, + u_int protocol) { u_short port = 0; int _socket = -1; @@ -73,7 +65,19 @@ pmap_getport (address, program, version, protocol) struct pmap parms; address->sin_port = htons (PMAPPORT); - client = clntudp_bufcreate (address, PMAPPROG, + if (protocol == IPPROTO_TCP) + { + // glibc does this: + ///* Don't need a reserved port to get ports from the portmapper. */ + //socket = __get_socket(address); // does socket(TCP),bind(),connect(address) + //if (_socket != -1) + // closeit = true; + // do we need/want to do the same? + client = clnttcp_create (address, PMAPPROG, + PMAPVERS, &_socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + } + else + client = clntudp_bufcreate (address, PMAPPROG, PMAPVERS, timeout, &_socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); if (client != (CLIENT *) NULL) { @@ -95,7 +99,7 @@ pmap_getport (address, program, version, protocol) } CLNT_DESTROY (client); } - /* (void)__close(_socket); CLNT_DESTROY already closed it */ + /* (void)close(_socket); CLNT_DESTROY already closed it */ address->sin_port = 0; return port; } diff --git a/libc/inet/rpc/pmap_clnt.c b/libc/inet/rpc/pmap_clnt.c index 8ac41f281..20a54313b 100644 --- a/libc/inet/rpc/pmap_clnt.c +++ b/libc/inet/rpc/pmap_clnt.c @@ -34,9 +34,6 @@ * Client interface to pmap rpc service. */ -#define __FORCE_GLIBC -#include <features.h> - #include <stdio.h> #include <unistd.h> #include <net/if.h> @@ -44,19 +41,10 @@ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> -#include <rpc/rpc.h> +#include "rpc_private.h" #include <rpc/pmap_prot.h> #include <rpc/pmap_clnt.h> -libc_hidden_proto(ioctl) -libc_hidden_proto(socket) -libc_hidden_proto(close) -libc_hidden_proto(perror) -libc_hidden_proto(exit) -libc_hidden_proto(clnt_perror) -libc_hidden_proto(clntudp_bufcreate) -libc_hidden_proto(xdr_bool) -libc_hidden_proto(xdr_pmap) /* * Same as get_myaddress, but we try to use the loopback @@ -122,7 +110,6 @@ static const struct timeval tottimeout = {60, 0}; * Set a mapping between program,version and port. * Calls the pmap service remotely to do the mapping. */ -libc_hidden_proto(pmap_set) bool_t pmap_set (u_long program, u_long version, int protocol, u_short port) { @@ -159,7 +146,6 @@ libc_hidden_def (pmap_set) * Remove the mapping between program,version and port. * Calls the pmap service remotely to do the un-mapping. */ -libc_hidden_proto(pmap_unset) bool_t pmap_unset (u_long program, u_long version) { diff --git a/libc/inet/rpc/pmap_prot.c b/libc/inet/rpc/pmap_prot.c index 0ae2c88f3..342dbad09 100644 --- a/libc/inet/rpc/pmap_prot.c +++ b/libc/inet/rpc/pmap_prot.c @@ -42,13 +42,9 @@ static char sccsid[] = "@(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro"; #include <rpc/xdr.h> #include <rpc/pmap_prot.h> -libc_hidden_proto(xdr_u_long) -libc_hidden_proto(xdr_pmap) bool_t -xdr_pmap (xdrs, regs) - XDR *xdrs; - struct pmap *regs; +xdr_pmap (XDR *xdrs, struct pmap *regs) { if (xdr_u_long (xdrs, ®s->pm_prog) && diff --git a/libc/inet/rpc/pmap_prot2.c b/libc/inet/rpc/pmap_prot2.c index 5adc4ee2e..f383757e8 100644 --- a/libc/inet/rpc/pmap_prot2.c +++ b/libc/inet/rpc/pmap_prot2.c @@ -42,9 +42,6 @@ static char sccsid[] = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro"; #include <rpc/xdr.h> #include <rpc/pmap_prot.h> -libc_hidden_proto(xdr_bool) -libc_hidden_proto(xdr_reference) -libc_hidden_proto(xdr_pmap) /* * What is going on with linked lists? (!) @@ -84,11 +81,8 @@ libc_hidden_proto(xdr_pmap) * the net, yet is the data that the pointer points to which is interesting; * this sounds like a job for xdr_reference! */ -libc_hidden_proto(xdr_pmaplist) bool_t -xdr_pmaplist (xdrs, rp) - XDR *xdrs; - struct pmaplist **rp; +xdr_pmaplist (XDR *xdrs, struct pmaplist **rp) { /* * more_elements is pre-computed in case the direction is diff --git a/libc/inet/rpc/pmap_rmt.c b/libc/inet/rpc/pmap_rmt.c index 759534aa7..2576e396b 100644 --- a/libc/inet/rpc/pmap_rmt.c +++ b/libc/inet/rpc/pmap_rmt.c @@ -39,12 +39,9 @@ static char sccsid[] = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro"; * Copyright (C) 1984, Sun Microsystems, Inc. */ -#define __FORCE_GLIBC -#include <features.h> - #include <unistd.h> #include <string.h> -#include <rpc/rpc.h> +#include "rpc_private.h" #include <rpc/pmap_prot.h> #include <rpc/pmap_clnt.h> #include <rpc/pmap_rmt.h> @@ -52,39 +49,12 @@ static char sccsid[] = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro"; #include <sys/socket.h> #include <stdio.h> #include <errno.h> -#undef _POSIX_SOURCE /* Ultrix <sys/param.h> needs --roland@gnu */ #include <sys/param.h> /* Ultrix needs before net/if --roland@gnu */ #include <net/if.h> #include <sys/ioctl.h> #include <arpa/inet.h> #define MAX_BROADCAST_SIZE 1400 -/* Experimentally off - libc_hidden_proto(memset) */ -libc_hidden_proto(ioctl) -libc_hidden_proto(perror) -libc_hidden_proto(socket) -libc_hidden_proto(close) -libc_hidden_proto(authunix_create_default) -libc_hidden_proto(xdrmem_create) -libc_hidden_proto(xdr_callmsg) -libc_hidden_proto(xdr_replymsg) -libc_hidden_proto(xdr_reference) -libc_hidden_proto(xdr_u_long) -libc_hidden_proto(xdr_void) -libc_hidden_proto(xdr_rmtcallres) -libc_hidden_proto(xdr_rmtcall_args) -libc_hidden_proto(inet_makeaddr) -libc_hidden_proto(inet_netof) -libc_hidden_proto(clntudp_create) -libc_hidden_proto(setsockopt) -libc_hidden_proto(recvfrom) -libc_hidden_proto(sendto) -libc_hidden_proto(poll) -libc_hidden_proto(fprintf) - - -extern u_long _create_xid (void) attribute_hidden; - static const struct timeval timeout = {3, 0}; /* @@ -95,13 +65,9 @@ static const struct timeval timeout = {3, 0}; * programs to do a lookup and call in one step. */ enum clnt_stat -pmap_rmtcall (addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_ptr) - struct sockaddr_in *addr; - u_long prog, vers, proc; - xdrproc_t xdrargs, xdrres; - caddr_t argsp, resp; - struct timeval tout; - u_long *port_ptr; +pmap_rmtcall (struct sockaddr_in *addr, u_long prog, u_long vers, u_long proc, + xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, caddr_t resp, + struct timeval tout, u_long *port_ptr) { int _socket = -1; CLIENT *client; @@ -173,9 +139,7 @@ libc_hidden_def(xdr_rmtcall_args) * written for XDR_DECODE direction only */ bool_t -xdr_rmtcallres (xdrs, crp) - XDR *xdrs; - struct rmtcallres *crp; +xdr_rmtcallres (XDR *xdrs, struct rmtcallres *crp) { caddr_t port_ptr; @@ -253,15 +217,15 @@ getbroadcastnets (struct in_addr *addrs, int sock, char *buf) enum clnt_stat -clnt_broadcast (prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) - u_long prog; /* program number */ - u_long vers; /* version number */ - u_long proc; /* procedure number */ - xdrproc_t xargs; /* xdr routine for args */ - caddr_t argsp; /* pointer to args */ - xdrproc_t xresults; /* xdr routine for results */ - caddr_t resultsp; /* pointer to results */ - resultproc_t eachresult; /* call with each result obtained */ +clnt_broadcast ( + u_long prog, /* program number */ + u_long vers, /* version number */ + u_long proc, /* procedure number */ + xdrproc_t xargs, /* xdr routine for args */ + caddr_t argsp, /* pointer to args */ + xdrproc_t xresults, /* xdr routine for results */ + caddr_t resultsp, /* pointer to results */ + resultproc_t eachresult /* call with each result obtained */) { enum clnt_stat stat = RPC_FAILED; AUTH *unix_auth = authunix_create_default (); diff --git a/libc/inet/rpc/rcmd.c b/libc/inet/rpc/rcmd.c index cd8d620c0..fdfaa0908 100644 --- a/libc/inet/rpc/rcmd.c +++ b/libc/inet/rpc/rcmd.c @@ -69,7 +69,6 @@ static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; #include <netinet/in.h> #include <arpa/inet.h> -#include <alloca.h> #include <signal.h> #include <fcntl.h> #include <netdb.h> @@ -77,7 +76,6 @@ static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; #include <pwd.h> #include <errno.h> #include <stdio.h> -#include <stdio_ext.h> #include <ctype.h> #include <string.h> #include <libintl.h> @@ -86,60 +84,13 @@ static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; #include <wchar.h> #endif #include <sys/uio.h> +#include <bits/uClibc_alloc.h> -/* Experimentally off - libc_hidden_proto(memcmp) */ -/* Experimentally off - libc_hidden_proto(strcat) */ -/* Experimentally off - libc_hidden_proto(strchr) */ -/* Experimentally off - libc_hidden_proto(strcmp) */ -/* Experimentally off - libc_hidden_proto(strcpy) */ -/* Experimentally off - libc_hidden_proto(strlen) */ -/* Experimentally off - libc_hidden_proto(strncmp) */ -/* Experimentally off - libc_hidden_proto(memmove) */ -libc_hidden_proto(getpid) -libc_hidden_proto(socket) -libc_hidden_proto(close) -libc_hidden_proto(fcntl) -libc_hidden_proto(read) -libc_hidden_proto(write) -libc_hidden_proto(perror) -libc_hidden_proto(lstat) -libc_hidden_proto(fstat) -libc_hidden_proto(tolower) -libc_hidden_proto(sysconf) -libc_hidden_proto(getline) -libc_hidden_proto(geteuid) -libc_hidden_proto(seteuid) -libc_hidden_proto(getpwnam_r) -libc_hidden_proto(gethostbyname) -libc_hidden_proto(gethostbyname_r) -libc_hidden_proto(fileno) -libc_hidden_proto(sleep) -libc_hidden_proto(inet_addr) -libc_hidden_proto(inet_ntoa) -libc_hidden_proto(herror) -libc_hidden_proto(bind) -libc_hidden_proto(connect) -libc_hidden_proto(sigblock) -libc_hidden_proto(snprintf) -libc_hidden_proto(poll) -libc_hidden_proto(accept) -libc_hidden_proto(listen) -libc_hidden_proto(sigsetmask) -libc_hidden_proto(getc_unlocked) -libc_hidden_proto(__fgetc_unlocked) -libc_hidden_proto(fopen) -libc_hidden_proto(fclose) -libc_hidden_proto(fprintf) -libc_hidden_proto(__h_errno_location) -#ifdef __UCLIBC_HAS_XLOCALE__ -libc_hidden_proto(__ctype_b_loc) -libc_hidden_proto(__ctype_tolower_loc) -#elif defined __UCLIBC_HAS_CTYPE_TABLES__ -libc_hidden_proto(__ctype_b) -libc_hidden_proto(__ctype_tolower) -#endif +/* sigsetmask and sigblock are not provided anymore, until this file is corrected, + * include the sources */ +#include "../../signal/sigblock.c" +#include "../../signal/sigsetmask.c" -libc_hidden_proto(rresvport) /* some forward declarations */ static int __ivaliduser2(FILE *hostf, u_int32_t raddr, @@ -148,11 +99,8 @@ static int iruserok2 (u_int32_t raddr, int superuser, const char *ruser, const char *luser, const char *rhost); -int rcmd(ahost, rport, locuser, remuser, cmd, fd2p) - char **ahost; - u_short rport; - const char *locuser, *remuser, *cmd; - int *fd2p; +int rcmd(char **ahost, u_short rport, const char *locuser, const char *remuser, + const char *cmd, int *fd2p) { #ifdef __UCLIBC_HAS_REENTRANT_RPC__ int herr; @@ -172,11 +120,7 @@ int rcmd(ahost, rport, locuser, remuser, cmd, fd2p) #ifdef __UCLIBC_HAS_REENTRANT_RPC__ hstbuflen = 1024; -#ifdef __ARCH_USE_MMU__ - tmphstbuf = alloca (hstbuflen); -#else - tmphstbuf = malloc (hstbuflen); -#endif + tmphstbuf = stack_heap_alloc(hstbuflen); while (gethostbyname_r (*ahost, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr) != 0 || hp == NULL) @@ -184,9 +128,7 @@ int rcmd(ahost, rport, locuser, remuser, cmd, fd2p) if (herr != NETDB_INTERNAL || errno != ERANGE) { __set_h_errno (herr); -#ifndef __ARCH_USE_MMU__ - free(tmphstbuf); -#endif + stack_heap_free(tmphstbuf); herror(*ahost); return -1; } @@ -194,17 +136,11 @@ int rcmd(ahost, rport, locuser, remuser, cmd, fd2p) { /* Enlarge the buffer. */ hstbuflen *= 2; -#ifdef __ARCH_USE_MMU__ - tmphstbuf = alloca (hstbuflen); -#else - free(tmphstbuf); - tmphstbuf = malloc (hstbuflen); -#endif + stack_heap_free(tmphstbuf); + tmphstbuf = stack_heap_alloc(hstbuflen); } } -#ifndef __ARCH_USE_MMU__ - free(tmphstbuf); -#endif + stack_heap_free(tmphstbuf); #else /* call the non-reentrant version */ if ((hp = gethostbyname(*ahost)) == NULL) { return -1; @@ -214,7 +150,7 @@ int rcmd(ahost, rport, locuser, remuser, cmd, fd2p) pfd[1].events = POLLIN; *ahost = hp->h_name; - oldmask = sigblock(sigmask(SIGURG)); /* __sigblock */ + oldmask = sigblock(__sigmask(SIGURG)); /* sigblock */ for (timo = 1, lport = IPPORT_RESERVED - 1;;) { s = rresvport(&lport); if (s < 0) { @@ -372,9 +308,8 @@ libc_hidden_def(rresvport) */ int __check_rhosts_file = 1; -int ruserok(rhost, superuser, ruser, luser) - const char *rhost, *ruser, *luser; - int superuser; +int ruserok(const char *rhost, int superuser, const char *ruser, + const char *luser) { struct hostent *hp; u_int32_t addr; @@ -388,35 +323,23 @@ int ruserok(rhost, superuser, ruser, luser) #ifdef __UCLIBC_HAS_REENTRANT_RPC__ buflen = 1024; -#ifdef __ARCH_USE_MMU__ - buffer = alloca (buflen); -#else - buffer = malloc (buflen); -#endif + buffer = stack_heap_alloc(buflen); while (gethostbyname_r (rhost, &hostbuf, buffer, buflen, &hp, &herr) != 0 || hp == NULL) { if (herr != NETDB_INTERNAL || errno != ERANGE) { -#ifndef __ARCH_USE_MMU__ - free(buffer); -#endif + stack_heap_free(buffer); return -1; } else { /* Enlarge the buffer. */ buflen *= 2; -#ifdef __ARCH_USE_MMU__ - buffer = alloca (buflen); -#else - free(buffer); - buffer = malloc (buflen); -#endif + stack_heap_free(buffer); + buffer = stack_heap_alloc(buflen); } } -#ifndef __ARCH_USE_MMU__ - free(buffer); -#endif + stack_heap_free(buffer); #else if ((hp = gethostbyname(rhost)) == NULL) { return -1; @@ -483,10 +406,8 @@ iruserfopen (const char *file, uid_t okuser) * Returns 0 if ok, -1 if not ok. */ static int -iruserok2 (raddr, superuser, ruser, luser, rhost) - u_int32_t raddr; - int superuser; - const char *ruser, *luser, *rhost; +iruserok2 (u_int32_t raddr, int superuser, const char *ruser, const char *luser, + const char *rhost) { FILE *hostf = NULL; int isbad = -1; @@ -511,23 +432,15 @@ iruserok2 (raddr, superuser, ruser, luser, rhost) #ifdef __UCLIBC_HAS_REENTRANT_RPC__ size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); struct passwd pwdbuf; -#ifdef __ARCH_USE_MMU__ - char *buffer = alloca (buflen); -#else - char *buffer = malloc (buflen); -#endif + char *buffer = stack_heap_alloc(buflen); if (getpwnam_r (luser, &pwdbuf, buffer, buflen, &pwd) != 0 || pwd == NULL) { -#ifndef __ARCH_USE_MMU__ - free(buffer); -#endif + stack_heap_free(buffer); return -1; } -#ifndef __ARCH_USE_MMU__ - free(buffer); -#endif + stack_heap_free(buffer); #else if ((pwd = getpwnam(luser)) == NULL) return -1; @@ -700,10 +613,8 @@ __isempty(char *p) * Returns 0 if positive match, -1 if _not_ ok. */ static int -__ivaliduser2(hostf, raddr, luser, ruser, rhost) - FILE *hostf; - u_int32_t raddr; - const char *luser, *ruser, *rhost; +__ivaliduser2(FILE *hostf, u_int32_t raddr, const char *luser, + const char *ruser, const char *rhost) { register const char *user; register char *p; diff --git a/libc/inet/rpc/rexec.c b/libc/inet/rpc/rexec.c index 2eb567ed2..e17be50b2 100644 --- a/libc/inet/rpc/rexec.c +++ b/libc/inet/rpc/rexec.c @@ -27,8 +27,6 @@ * SUCH DAMAGE. */ -#define __FORCE_GLIBC -#include <features.h> #include <sys/types.h> #include <sys/socket.h> @@ -41,35 +39,14 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> - -/* Experimentally off - libc_hidden_proto(memset) */ -/* Experimentally off - libc_hidden_proto(strlen) */ -/* Experimentally off - libc_hidden_proto(strncpy) */ -libc_hidden_proto(read) -libc_hidden_proto(write) -libc_hidden_proto(close) -libc_hidden_proto(socket) -libc_hidden_proto(perror) -libc_hidden_proto(sprintf) -libc_hidden_proto(snprintf) -libc_hidden_proto(getsockname) -libc_hidden_proto(getnameinfo) -libc_hidden_proto(getaddrinfo) -libc_hidden_proto(freeaddrinfo) -libc_hidden_proto(sleep) -libc_hidden_proto(atoi) -libc_hidden_proto(connect) -libc_hidden_proto(accept) -libc_hidden_proto(listen) -libc_hidden_proto(ruserpass) +#include <malloc.h> #define SA_LEN(_x) __libc_sa_len((_x)->sa_family) -extern int __libc_sa_len (sa_family_t __af) __THROW attribute_hidden; +extern int __libc_sa_len(sa_family_t __af) __THROW attribute_hidden; -int rexecoptions; -char ahostbuf[NI_MAXHOST] attribute_hidden; +/* int rexecoptions; - google does not know it */ +static char *ahostbuf = NULL; -libc_hidden_proto(rexec_af) int rexec_af(char **ahost, int rport, const char *name, const char *pass, const char *cmd, int *fd2p, sa_family_t af) { @@ -83,27 +60,33 @@ rexec_af(char **ahost, int rport, const char *name, const char *pass, const char int gai; char servbuff[NI_MAXSERV]; - snprintf(servbuff, sizeof(servbuff), "%d", ntohs(rport)); - servbuff[sizeof(servbuff) - 1] = '\0'; + if (sizeof(servbuff) < sizeof(int)*3 + 2) { + snprintf(servbuff, sizeof(servbuff), "%d", ntohs(rport)); + servbuff[sizeof(servbuff) - 1] = '\0'; + } else { + sprintf(servbuff, "%d", ntohs(rport)); + } memset(&hints, '\0', sizeof(hints)); hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; gai = getaddrinfo(*ahost, servbuff, &hints, &res0); - if (gai){ + if (gai) { /* XXX: set errno? */ return -1; } - if (res0->ai_canonname){ - strncpy(ahostbuf, res0->ai_canonname, sizeof(ahostbuf)); - ahostbuf[sizeof(ahostbuf)-1] = '\0'; + if (res0->ai_canonname) { + if (!ahostbuf) + ahostbuf = __uc_malloc(NI_MAXHOST); + strncpy(ahostbuf, res0->ai_canonname, NI_MAXHOST); + ahostbuf[NI_MAXHOST-1] = '\0'; *ahost = ahostbuf; } - else{ + else { *ahost = NULL; - __set_errno (ENOENT); + __set_errno(ENOENT); return -1; } ruserpass(res0->ai_canonname, &name, &pass); @@ -111,7 +94,7 @@ retry: s = socket(res0->ai_family, res0->ai_socktype, 0); if (s < 0) { perror("rexec: socket"); - return (-1); + return -1; } if (connect(s, res0->ai_addr, res0->ai_addrlen) < 0) { if (errno == ECONNREFUSED && timo <= 16) { @@ -121,7 +104,7 @@ retry: goto retry; } perror(res0->ai_canonname); - return (-1); + return -1; } if (fd2p == 0) { (void) write(s, "", 1); @@ -134,10 +117,10 @@ retry: s2 = socket(res0->ai_family, res0->ai_socktype, 0); if (s2 < 0) { (void) close(s); - return (-1); + return -1; } listen(s2, 1); - sa2len = sizeof (sa2); + sa2len = sizeof(sa2); if (getsockname(s2, (struct sockaddr *)&sa2, &sa2len) < 0) { perror("getsockname"); (void) close(s2); @@ -154,15 +137,16 @@ retry: port = atoi(servbuff); (void) sprintf(num, "%u", port); (void) write(s, num, strlen(num)+1); - { socklen_t len = sizeof (from); - s3 = TEMP_FAILURE_RETRY (accept(s2, (struct sockaddr *)&from, - &len)); - close(s2); - if (s3 < 0) { - perror("accept"); - port = 0; - goto bad; - } + { + socklen_t len = sizeof(from); + s3 = TEMP_FAILURE_RETRY(accept(s2, + (struct sockaddr *)&from, &len)); + close(s2); + if (s3 < 0) { + perror("accept"); + port = 0; + goto bad; + } } *fd2p = s3; } @@ -174,9 +158,9 @@ retry: /* We don't need the memory allocated for the name and the password in ruserpass anymore. */ if (name != orig_name) - free ((char *) name); + free((char *) name); if (pass != orig_pass) - free ((char *) pass); + free((char *) pass); if (read(s, &c, 1) != 1) { perror(*ahost); @@ -191,22 +175,19 @@ retry: goto bad; } freeaddrinfo(res0); - return (s); + return s; bad: if (port) (void) close(*fd2p); (void) close(s); freeaddrinfo(res0); - return (-1); + return -1; } libc_hidden_def(rexec_af) int -rexec(ahost, rport, name, pass, cmd, fd2p) - char **ahost; - int rport; - const char *name, *pass, *cmd; - int *fd2p; +rexec(char **ahost, int rport, const char *name, const char *pass, + const char *cmd, int *fd2p) { return rexec_af(ahost, rport, name, pass, cmd, fd2p, AF_INET); } diff --git a/libc/inet/rpc/rpc_cmsg.c b/libc/inet/rpc/rpc_cmsg.c index 3206aae55..06d042ecb 100644 --- a/libc/inet/rpc/rpc_cmsg.c +++ b/libc/inet/rpc/rpc_cmsg.c @@ -38,24 +38,14 @@ static char sccsid[] = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro"; * */ -#define __FORCE_GLIBC -#include <features.h> - #include <string.h> #include <sys/param.h> #include <rpc/rpc.h> -/* Experimentally off - libc_hidden_proto(memcpy) */ -libc_hidden_proto(xdr_enum) -libc_hidden_proto(xdr_opaque) -libc_hidden_proto(xdr_u_int) -libc_hidden_proto(xdr_u_long) -libc_hidden_proto(xdr_opaque_auth) /* * XDR a call message */ -libc_hidden_proto(xdr_callmsg) bool_t xdr_callmsg (XDR *xdrs, struct rpc_msg *cmsg) { diff --git a/libc/inet/rpc/rpc_dtablesize.c b/libc/inet/rpc/rpc_dtablesize.c index 11a7ad457..45cab6212 100644 --- a/libc/inet/rpc/rpc_dtablesize.c +++ b/libc/inet/rpc/rpc_dtablesize.c @@ -31,20 +31,14 @@ static char sccsid[] = "@(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro"; #endif -#define __FORCE_GLIBC -#define __USE_BSD -#include <features.h> - #include <unistd.h> #include <rpc/clnt.h> -libc_hidden_proto(getdtablesize) /* * Cache the result of getdtablesize(), so we don't have to do an * expensive system call every time. */ -libc_hidden_proto(_rpc_dtablesize) int _rpc_dtablesize(void) { diff --git a/libc/inet/rpc/rpc_private.h b/libc/inet/rpc/rpc_private.h index 15250059a..9e01df49a 100644 --- a/libc/inet/rpc/rpc_private.h +++ b/libc/inet/rpc/rpc_private.h @@ -1,10 +1,11 @@ -#ifndef _RPC_RPC_H +#ifndef _RPC_PRIVATE_H +#define _RPC_PRIVATE_H #include <rpc/rpc.h> +#include <libintl.h> /* Now define the internal interfaces. */ extern u_long _create_xid (void) attribute_hidden; -libc_hidden_proto(__rpc_thread_createerr) /* * Multi-threaded support @@ -13,14 +14,13 @@ libc_hidden_proto(__rpc_thread_createerr) */ #ifdef __UCLIBC_HAS_THREADS__ #include <pthread.h> +#include <bits/libc-lock.h> struct rpc_thread_variables { fd_set svc_fdset_s; /* Global, rpc_common.c */ struct rpc_createerr rpc_createerr_s; /* Global, rpc_common.c */ struct pollfd *svc_pollfd_s; /* Global, rpc_common.c */ int svc_max_pollfd_s; /* Global, rpc_common.c */ - void *authnone_private_s; /* auth_none.c */ - void *clnt_perr_buf_s; /* clnt_perr.c */ void *clntraw_private_s; /* clnt_raw.c */ diff --git a/libc/inet/rpc/rpc_prot.c b/libc/inet/rpc/rpc_prot.c index 74658e654..d43214d18 100644 --- a/libc/inet/rpc/rpc_prot.c +++ b/libc/inet/rpc/rpc_prot.c @@ -44,18 +44,10 @@ static char sccsid[] = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro"; * routines are also in this program. */ -#define __FORCE_GLIBC -#include <features.h> - #include <sys/param.h> #include <rpc/rpc.h> -libc_hidden_proto(xdr_bytes) -libc_hidden_proto(xdr_union) -libc_hidden_proto(xdr_enum) -libc_hidden_proto(xdr_opaque) -libc_hidden_proto(xdr_u_long) /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ @@ -63,7 +55,6 @@ libc_hidden_proto(xdr_u_long) * XDR an opaque authentication struct * (see auth.h) */ -libc_hidden_proto(xdr_opaque_auth) bool_t xdr_opaque_auth (XDR *xdrs, struct opaque_auth *ap) { @@ -89,7 +80,6 @@ xdr_des_block (XDR *xdrs, des_block *blkp) /* * XDR the MSG_ACCEPTED part of a reply message union */ -libc_hidden_proto(xdr_accepted_reply) bool_t xdr_accepted_reply (XDR *xdrs, struct accepted_reply *ar) { @@ -116,7 +106,6 @@ libc_hidden_def(xdr_accepted_reply) /* * XDR the MSG_DENIED part of a reply message union */ -libc_hidden_proto(xdr_rejected_reply) bool_t xdr_rejected_reply (XDR *xdrs, struct rejected_reply *rr) { @@ -146,7 +135,6 @@ static const struct xdr_discrim reply_dscrm[3] = /* * XDR a reply message */ -libc_hidden_proto(xdr_replymsg) bool_t xdr_replymsg (XDR *xdrs, struct rpc_msg *rmsg) { @@ -166,7 +154,6 @@ libc_hidden_def(xdr_replymsg) * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. * The rm_xid is not really static, but the user can easily munge on the fly. */ -libc_hidden_proto(xdr_callhdr) bool_t xdr_callhdr (XDR *xdrs, struct rpc_msg *cmsg) { @@ -229,7 +216,7 @@ rejected (enum reject_stat rjct_stat, { switch (rjct_stat) { - case RPC_VERSMISMATCH: + case RPC_MISMATCH: error->re_status = RPC_VERSMISMATCH; return; case AUTH_ERROR: @@ -247,7 +234,6 @@ rejected (enum reject_stat rjct_stat, /* * given a reply message, fills in the error */ -libc_hidden_proto(_seterr_reply) void _seterr_reply (struct rpc_msg *msg, struct rpc_err *error) diff --git a/libc/inet/rpc/rpc_thread.c b/libc/inet/rpc/rpc_thread.c index 2c7b8c1ea..d8d753421 100644 --- a/libc/inet/rpc/rpc_thread.c +++ b/libc/inet/rpc/rpc_thread.c @@ -4,20 +4,15 @@ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ -#define __FORCE_GLIBC -#include <features.h> #include <stdio.h> #include <assert.h> #include "rpc_private.h" -libc_hidden_proto(__rpc_thread_svc_fdset) -libc_hidden_proto(__rpc_thread_createerr) -libc_hidden_proto(__rpc_thread_svc_pollfd) -libc_hidden_proto(__rpc_thread_svc_max_pollfd) #ifdef __UCLIBC_HAS_THREADS__ #include <bits/libc-tsd.h> +#include <bits/libc-lock.h> /* Variable used in non-threaded applications or for the first thread. */ static struct rpc_thread_variables __libc_tsd_RPC_VARS_mem; @@ -34,8 +29,7 @@ __rpc_thread_destroy (void) if (tvp != NULL && tvp != &__libc_tsd_RPC_VARS_mem) { __rpc_thread_svc_cleanup (); __rpc_thread_clnt_cleanup (); - //__rpc_thread_key_cleanup (); - free (tvp->authnone_private_s); + /*__rpc_thread_key_cleanup (); */ free (tvp->clnt_perr_buf_s); free (tvp->clntraw_private_s); free (tvp->svcraw_private_s); diff --git a/libc/inet/rpc/rtime.c b/libc/inet/rpc/rtime.c index 6190868ad..02016bf82 100644 --- a/libc/inet/rpc/rtime.c +++ b/libc/inet/rpc/rtime.c @@ -43,9 +43,6 @@ static char sccsid[] = "@(#)rtime.c 2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 S * what unix uses. */ -#define __FORCE_GLIBC -#include <features.h> - #include <stdio.h> #include <unistd.h> #include <rpc/rpc.h> @@ -58,14 +55,6 @@ static char sccsid[] = "@(#)rtime.c 2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 S #include <errno.h> #include <netinet/in.h> -libc_hidden_proto(read) -libc_hidden_proto(socket) -libc_hidden_proto(close) -libc_hidden_proto(connect) -libc_hidden_proto(recvfrom) -libc_hidden_proto(sendto) -libc_hidden_proto(poll) -libc_hidden_proto(rtime) #define NYEARS (u_long)(1970 - 1900) #define TOFFSET (u_long)(60*60*24*(365*NYEARS + (NYEARS/4))) @@ -158,4 +147,3 @@ rtime (struct sockaddr_in *addrp, struct rpc_timeval *timep, timep->tv_usec = 0; return 0; } -libc_hidden_def (rtime) diff --git a/libc/inet/rpc/ruserpass.c b/libc/inet/rpc/ruserpass.c index ad6e703c4..9197763a3 100644 --- a/libc/inet/rpc/ruserpass.c +++ b/libc/inet/rpc/ruserpass.c @@ -27,8 +27,6 @@ * SUCH DAMAGE. */ -#define __FORCE_GLIBC -#include <features.h> #include <sys/types.h> #include <sys/stat.h> @@ -37,34 +35,14 @@ #include <errno.h> #include <netdb.h> #include <stdio.h> -#include <stdio_ext.h> +#ifdef __UCLIBC_HAS_THREADS__ +# include <stdio_ext.h> +#endif #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <libintl.h> -/* Experimentally off - libc_hidden_proto(strcat) */ -/* Experimentally off - libc_hidden_proto(strchr) */ -/* Experimentally off - libc_hidden_proto(strcmp) */ -/* Experimentally off - libc_hidden_proto(strcpy) */ -/* Experimentally off - libc_hidden_proto(strlen) */ -/* Experimentally off - libc_hidden_proto(strcasecmp) */ -/* Experimentally off - libc_hidden_proto(strncasecmp) */ -libc_hidden_proto(getenv) -libc_hidden_proto(printf) -libc_hidden_proto(fstat) -libc_hidden_proto(__fsetlocking) -libc_hidden_proto(getgid) -libc_hidden_proto(getuid) -libc_hidden_proto(getegid) -libc_hidden_proto(geteuid) -libc_hidden_proto(gethostname) -libc_hidden_proto(fileno) -libc_hidden_proto(fopen) -libc_hidden_proto(fclose) -libc_hidden_proto(getc_unlocked) -libc_hidden_proto(__fgetc_unlocked) - -#define _(X) (X) /* #include "ftp_var.h" */ static int token (void); @@ -114,7 +92,6 @@ static const struct toktab { /* ruserpass - remote password check. This function also exists in glibc but is undocumented */ -libc_hidden_proto(ruserpass) int ruserpass(const char *host, const char **aname, const char **apass) { char *hdir, *buf, *tmp; @@ -308,7 +285,7 @@ bad: libc_hidden_def(ruserpass) static int -token() +token(void) { char *cp; int c; diff --git a/libc/inet/rpc/sa_len.c b/libc/inet/rpc/sa_len.c index 3b37eba44..886fb3e34 100644 --- a/libc/inet/rpc/sa_len.c +++ b/libc/inet/rpc/sa_len.c @@ -12,17 +12,14 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ -#define __FORCE_GLIBC -#include <features.h> #include <sys/socket.h> #include <netinet/in.h> -#include <netipx/ipx.h> #include <sys/un.h> #if 0 +#include <netipx/ipx.h> #include <netash/ash.h> #include <netatalk/at.h> #include <netax25/ax25.h> @@ -52,10 +49,14 @@ int __libc_sa_len (sa_family_t af) #endif case AF_INET: return sizeof (struct sockaddr_in); +#ifdef __UCLIBC_HAS_IPV6__ case AF_INET6: return sizeof (struct sockaddr_in6); +#endif +#if 0 case AF_IPX: return sizeof (struct sockaddr_ipx); +#endif case AF_LOCAL: return sizeof (struct sockaddr_un); } diff --git a/libc/inet/rpc/svc.c b/libc/inet/rpc/svc.c index 253c06379..c3d55185b 100644 --- a/libc/inet/rpc/svc.c +++ b/libc/inet/rpc/svc.c @@ -36,26 +36,16 @@ * Copyright (C) 1984, Sun Microsystems, Inc. */ -#define __FORCE_GLIBC -#include <features.h> - #include <errno.h> #include <unistd.h> +#include <string.h> #include "rpc_private.h" #include <rpc/svc.h> #include <rpc/pmap_clnt.h> #include <sys/poll.h> -/* Experimentally off - libc_hidden_proto(ffs) */ -libc_hidden_proto(pmap_set) -libc_hidden_proto(pmap_unset) -libc_hidden_proto(_authenticate) -libc_hidden_proto(_rpc_dtablesize) /* used by svc_[max_]pollfd */ -libc_hidden_proto(__rpc_thread_svc_pollfd) -libc_hidden_proto(__rpc_thread_svc_max_pollfd) /* used by svc_fdset */ -libc_hidden_proto(__rpc_thread_svc_fdset) #ifdef __UCLIBC_HAS_THREADS__ #define xports (*(SVCXPRT ***)&RPC_THREAD_VARIABLE(svc_xports_s)) @@ -85,7 +75,6 @@ static struct svc_callout *svc_head; /* *************** SVCXPRT related stuff **************** */ /* Activate a transport handle. */ -libc_hidden_proto(xprt_register) void xprt_register (SVCXPRT *xprt) { @@ -129,7 +118,6 @@ xprt_register (SVCXPRT *xprt) libc_hidden_def(xprt_register) /* De-activate a transport handle. */ -libc_hidden_proto(xprt_unregister) void xprt_unregister (SVCXPRT *xprt) { @@ -175,7 +163,6 @@ done: /* Add a service program to the callout list. The dispatch routine will be called when a rpc request for this program number comes in. */ -libc_hidden_proto(svc_register) bool_t svc_register (SVCXPRT * xprt, rpcprog_t prog, rpcvers_t vers, void (*dispatch) (struct svc_req *, SVCXPRT *), @@ -210,7 +197,6 @@ pmap_it: libc_hidden_def(svc_register) /* Remove a service program from the callout list. */ -libc_hidden_proto(svc_unregister) void svc_unregister (rpcprog_t prog, rpcvers_t vers) { @@ -235,7 +221,6 @@ libc_hidden_def(svc_unregister) /* ******************* REPLY GENERATION ROUTINES ************ */ /* Send a reply to an rpc request */ -libc_hidden_proto(svc_sendreply) bool_t svc_sendreply (register SVCXPRT *xprt, xdrproc_t xdr_results, caddr_t xdr_location) @@ -266,7 +251,6 @@ svcerr_noproc (register SVCXPRT *xprt) } /* Can't decode args error reply */ -libc_hidden_proto(svcerr_decode) void svcerr_decode (register SVCXPRT *xprt) { @@ -294,7 +278,6 @@ svcerr_systemerr (register SVCXPRT *xprt) } /* Authentication error reply */ -libc_hidden_proto(svcerr_auth) void svcerr_auth (SVCXPRT *xprt, enum auth_stat why) { @@ -316,7 +299,6 @@ svcerr_weakauth (SVCXPRT *xprt) } /* Program unavailable error reply */ -libc_hidden_proto(svcerr_noprog) void svcerr_noprog (register SVCXPRT *xprt) { @@ -331,7 +313,6 @@ svcerr_noprog (register SVCXPRT *xprt) libc_hidden_def(svcerr_noprog) /* Program version mismatch error reply */ -libc_hidden_proto(svcerr_progvers) void svcerr_progvers (register SVCXPRT *xprt, rpcvers_t low_vers, rpcvers_t high_vers) @@ -366,7 +347,6 @@ libc_hidden_def(svcerr_progvers) * is mallocated in kernel land. */ -libc_hidden_proto(svc_getreq_common) void svc_getreq_common (const int fd) { @@ -458,7 +438,6 @@ svc_getreq_common (const int fd) } libc_hidden_def(svc_getreq_common) -libc_hidden_proto(svc_getreqset) void svc_getreqset (fd_set *readfds) { @@ -469,6 +448,8 @@ svc_getreqset (fd_set *readfds) register int bit; setsize = _rpc_dtablesize (); + if (setsize > FD_SETSIZE) + setsize = FD_SETSIZE; maskp = (u_int32_t *) readfds->fds_bits; for (sock = 0; sock < setsize; sock += 32) for (mask = *maskp++; (bit = ffs (mask)); mask ^= (1 << (bit - 1))) @@ -476,7 +457,6 @@ svc_getreqset (fd_set *readfds) } libc_hidden_def(svc_getreqset) -libc_hidden_proto(svc_getreq) void svc_getreq (int rdfds) { @@ -488,7 +468,6 @@ svc_getreq (int rdfds) } libc_hidden_def(svc_getreq) -libc_hidden_proto(svc_getreq_poll) void svc_getreq_poll (struct pollfd *pfdp, int pollretval) { diff --git a/libc/inet/rpc/svc_auth.c b/libc/inet/rpc/svc_auth.c index 1a5dcf0ca..c902b46d2 100644 --- a/libc/inet/rpc/svc_auth.c +++ b/libc/inet/rpc/svc_auth.c @@ -58,9 +58,9 @@ static char sccsid[] = "@(#)svc_auth.c 1.19 87/08/11 Copyr 1984 Sun Micro"; static enum auth_stat _svcauth_null (struct svc_req *, struct rpc_msg *); /* no authentication */ -extern enum auth_stat _svcauth_unix (struct svc_req *, struct rpc_msg *); +extern enum auth_stat _svcauth_unix (struct svc_req *, struct rpc_msg *) attribute_hidden; /* unix style (uid, gids) */ -extern enum auth_stat _svcauth_short (struct svc_req *, struct rpc_msg *); +extern enum auth_stat _svcauth_short (struct svc_req *, struct rpc_msg *) attribute_hidden; /* short hand unix style */ #ifdef CONFIG_AUTH_DES extern enum auth_stat _svcauth_des (struct svc_req *, struct rpc_msg *); @@ -101,7 +101,6 @@ svcauthsw[] = * There is an assumption that any flavour less than AUTH_NULL is * invalid. */ -libc_hidden_proto(_authenticate) enum auth_stat _authenticate (register struct svc_req *rqst, struct rpc_msg *msg) { diff --git a/libc/inet/rpc/svc_authux.c b/libc/inet/rpc/svc_authux.c index 64c911f93..ca1a645e4 100644 --- a/libc/inet/rpc/svc_authux.c +++ b/libc/inet/rpc/svc_authux.c @@ -38,18 +38,11 @@ * Copyright (C) 1984, Sun Microsystems, Inc. */ -#define __FORCE_GLIBC -#include <features.h> - #include <stdio.h> #include <string.h> #include <rpc/rpc.h> #include <rpc/svc.h> -/* Experimentally off - libc_hidden_proto(memcpy) */ -libc_hidden_proto(printf) -libc_hidden_proto(xdrmem_create) -libc_hidden_proto(xdr_authunix_parms) /* * Unix longhand authenticator diff --git a/libc/inet/rpc/svc_raw.c b/libc/inet/rpc/svc_raw.c index 0cdbbb89a..8156042fe 100644 --- a/libc/inet/rpc/svc_raw.c +++ b/libc/inet/rpc/svc_raw.c @@ -40,14 +40,9 @@ static char sccsid[] = "@(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro"; * Copyright (C) 1984, Sun Microsystems, Inc. */ -#define __FORCE_GLIBC -#include <features.h> #include "rpc_private.h" #include <rpc/svc.h> -libc_hidden_proto(xdrmem_create) -libc_hidden_proto(xdr_callmsg) -libc_hidden_proto(xdr_replymsg) /* * This is the "network" that we will be moving data over @@ -72,7 +67,7 @@ static bool_t svcraw_reply (SVCXPRT *, struct rpc_msg *); static bool_t svcraw_freeargs (SVCXPRT *, xdrproc_t, caddr_t); static void svcraw_destroy (SVCXPRT *); -static struct xp_ops server_ops = +static const struct xp_ops server_ops = { svcraw_recv, svcraw_stat, @@ -108,9 +103,7 @@ svcraw_stat (SVCXPRT *xprt attribute_unused) } static bool_t -svcraw_recv (xprt, msg) - SVCXPRT *xprt attribute_unused; - struct rpc_msg *msg; +svcraw_recv (SVCXPRT *xprt attribute_unused, struct rpc_msg *msg) { struct svcraw_private_s *srp = svcraw_private; XDR *xdrs; diff --git a/libc/inet/rpc/svc_run.c b/libc/inet/rpc/svc_run.c index 50e5fcd79..f3e020951 100644 --- a/libc/inet/rpc/svc_run.c +++ b/libc/inet/rpc/svc_run.c @@ -31,20 +31,12 @@ * Wait for input, call server program. */ -#define __FORCE_GLIBC -#include <features.h> - #include <errno.h> #include <unistd.h> #include <sys/poll.h> -#include <rpc/rpc.h> +#include "rpc_private.h" -libc_hidden_proto(perror) -libc_hidden_proto(svc_getreq_poll) -libc_hidden_proto(poll) /* used by svc_[max_]pollfd */ -libc_hidden_proto(__rpc_thread_svc_pollfd) -libc_hidden_proto(__rpc_thread_svc_max_pollfd) /* This function can be used as a signal handler to terminate the server loop. */ diff --git a/libc/inet/rpc/svc_simple.c b/libc/inet/rpc/svc_simple.c index 72c272aa7..c770938a1 100644 --- a/libc/inet/rpc/svc_simple.c +++ b/libc/inet/rpc/svc_simple.c @@ -38,9 +38,6 @@ static char sccsid[] = "@(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro"; * Copyright (C) 1984, Sun Microsystems, Inc. */ -#define __FORCE_GLIBC -#include <features.h> - #include <stdio.h> #include <string.h> #include <unistd.h> @@ -49,25 +46,6 @@ static char sccsid[] = "@(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro"; #include <sys/socket.h> #include <netdb.h> -#ifdef USE_IN_LIBIO -# include <wchar.h> -# include <libio/iolibio.h> -# define fputs(s, f) _IO_fputs (s, f) -#endif - -/* Experimentally off - libc_hidden_proto(strdup) */ -/* Experimentally off - libc_hidden_proto(memset) */ -libc_hidden_proto(asprintf) -libc_hidden_proto(fputs) -libc_hidden_proto(write) -libc_hidden_proto(exit) -libc_hidden_proto(svc_sendreply) -libc_hidden_proto(svc_register) -libc_hidden_proto(svcerr_decode) -libc_hidden_proto(svcudp_create) -libc_hidden_proto(pmap_unset) -libc_hidden_proto(xdr_void) - struct proglst_ { char *(*p_progname) (char *); @@ -139,12 +117,7 @@ registerrpc (u_long prognum, u_long versnum, u_long procnum, return 0; err_out: -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) __fwprintf (stderr, L"%s", buf); - else -#endif - (void) fputs (buf, stderr); + (void) fputs (buf, stderr); free (buf); return -1; } @@ -198,12 +171,7 @@ universal (struct svc_req *rqstp, SVCXPRT *transp_l) return; } (void) asprintf (&buf, _("never registered prog %d\n"), prog); -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else -#endif - fputs (buf, stderr); + fputs (buf, stderr); free (buf); exit (1); } diff --git a/libc/inet/rpc/svc_tcp.c b/libc/inet/rpc/svc_tcp.c index 5e4667940..f0acf35dc 100644 --- a/libc/inet/rpc/svc_tcp.c +++ b/libc/inet/rpc/svc_tcp.c @@ -41,49 +41,15 @@ static char sccsid[] = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; * and a record/tcp stream. */ -#define __FORCE_GLIBC -#include <features.h> - #include <stdio.h> #include <unistd.h> #include <string.h> -#include <rpc/rpc.h> +#include "rpc_private.h" #include <sys/socket.h> #include <sys/poll.h> #include <errno.h> #include <stdlib.h> -#ifdef USE_IN_LIBIO -# include <wchar.h> -# include <libio/iolibio.h> -# define fputs(s, f) _IO_fputs (s, f) -#endif - -/* Experimentally off - libc_hidden_proto(memset) */ -/* Experimentally off - libc_hidden_proto(memcpy) */ -libc_hidden_proto(socket) -libc_hidden_proto(close) -libc_hidden_proto(read) -libc_hidden_proto(write) -libc_hidden_proto(perror) -libc_hidden_proto(xdrrec_create) -libc_hidden_proto(xdrrec_endofrecord) -libc_hidden_proto(xdrrec_skiprecord) -libc_hidden_proto(xdrrec_eof) -libc_hidden_proto(xdr_callmsg) -libc_hidden_proto(xdr_replymsg) -libc_hidden_proto(xprt_register) -libc_hidden_proto(xprt_unregister) -libc_hidden_proto(getsockname) -libc_hidden_proto(bind) -libc_hidden_proto(bindresvport) -libc_hidden_proto(poll) -libc_hidden_proto(accept) -libc_hidden_proto(listen) -libc_hidden_proto(fputs) -libc_hidden_proto(fclose) -libc_hidden_proto(abort) - /* * Ops vector for TCP/IP based rpc service handle */ @@ -204,12 +170,7 @@ svctcp_create (int sock, u_int sendsize, u_int recvsize) xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); if (r == NULL || xprt == NULL) { -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) __fwprintf (stderr, L"%s", _("svctcp_create: out of memory\n")); - else -#endif - (void) fputs (_("svctcp_create: out of memory\n"), stderr); + (void) fputs (_("svctcp_create: out of memory\n"), stderr); mem_free (r, sizeof (*r)); mem_free (xprt, sizeof (SVCXPRT)); return NULL; @@ -249,13 +210,7 @@ makefd_xprt (int fd, u_int sendsize, u_int recvsize) cd = (struct tcp_conn *) mem_alloc (sizeof (struct tcp_conn)); if (xprt == (SVCXPRT *) NULL || cd == NULL) { -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) __fwprintf (stderr, L"%s", - _("svc_tcp: makefd_xprt: out of memory\n")); - else -#endif - (void) fputs (_("svc_tcp: makefd_xprt: out of memory\n"), stderr); + (void) fputs (_("svc_tcp: makefd_xprt: out of memory\n"), stderr); mem_free (xprt, sizeof (SVCXPRT)); mem_free (cd, sizeof (struct tcp_conn)); return NULL; diff --git a/libc/inet/rpc/svc_udp.c b/libc/inet/rpc/svc_udp.c index e2c97bdc5..456c6ded2 100644 --- a/libc/inet/rpc/svc_udp.c +++ b/libc/inet/rpc/svc_udp.c @@ -39,13 +39,10 @@ static char sccsid[] = "@(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro"; * Copyright (C) 1984, Sun Microsystems, Inc. */ -#define __FORCE_GLIBC -#include <features.h> - #include <stdio.h> #include <unistd.h> #include <string.h> -#include <rpc/rpc.h> +#include "rpc_private.h" #include <sys/socket.h> #include <errno.h> @@ -53,35 +50,6 @@ static char sccsid[] = "@(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro"; #include <sys/uio.h> #endif -#ifdef USE_IN_LIBIO -# include <wchar.h> -# include <libio/iolibio.h> -# define fputs(s, f) _IO_fputs (s, f) -libc_hidden_proto(fwprintf) -#endif - -/* Experimentally off - libc_hidden_proto(memcmp) */ -/* Experimentally off - libc_hidden_proto(memcpy) */ -/* Experimentally off - libc_hidden_proto(memset) */ -libc_hidden_proto(perror) -libc_hidden_proto(socket) -libc_hidden_proto(close) -libc_hidden_proto(xprt_register) -libc_hidden_proto(xprt_unregister) -libc_hidden_proto(xdrmem_create) -libc_hidden_proto(xdr_callmsg) -libc_hidden_proto(xdr_replymsg) -libc_hidden_proto(getsockname) -libc_hidden_proto(setsockopt) -libc_hidden_proto(bind) -libc_hidden_proto(bindresvport) -libc_hidden_proto(recvfrom) -libc_hidden_proto(sendto) -libc_hidden_proto(recvmsg) -libc_hidden_proto(sendmsg) -libc_hidden_proto(fputs) -libc_hidden_proto(fprintf) - #define rpc_buffer(xprt) ((xprt)->xp_p1) #ifndef MAX #define MAX(a, b) ((a > b) ? a : b) @@ -134,7 +102,6 @@ struct svcudp_data * see (svc.h, xprt_register). * The routines returns NULL if a problem occurred. */ -libc_hidden_proto(svcudp_bufcreate) SVCXPRT * svcudp_bufcreate (int sock, u_int sendsz, u_int recvsz) { @@ -174,12 +141,7 @@ svcudp_bufcreate (int sock, u_int sendsz, u_int recvsz) buf = mem_alloc (((MAX (sendsz, recvsz) + 3) / 4) * 4); if (xprt == NULL || su == NULL || buf == NULL) { -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", _("svcudp_create: out of memory\n")); - else -#endif - (void) fputs (_("svcudp_create: out of memory\n"), stderr); + (void) fputs (_("svcudp_create: out of memory\n"), stderr); mem_free (xprt, sizeof (SVCXPRT)); mem_free (su, sizeof (*su)); mem_free (buf, ((MAX (sendsz, recvsz) + 3) / 4) * 4); @@ -200,13 +162,7 @@ svcudp_bufcreate (int sock, u_int sendsz, u_int recvsz) + sizeof(struct cmsghdr) + sizeof (struct in_pktinfo)) > sizeof (xprt->xp_pad)) { -# ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", - _("svcudp_create: xp_pad is too small for IP_PKTINFO\n")); - else -# endif - (void) fputs (_("svcudp_create: xp_pad is too small for IP_PKTINFO\n"), + (void) fputs (_("svcudp_create: xp_pad is too small for IP_PKTINFO\n"), stderr); return NULL; } @@ -226,7 +182,6 @@ svcudp_bufcreate (int sock, u_int sendsz, u_int recvsz) } libc_hidden_def(svcudp_bufcreate) -libc_hidden_proto(svcudp_create) SVCXPRT * svcudp_create (int sock) { @@ -236,17 +191,14 @@ svcudp_create (int sock) libc_hidden_def(svcudp_create) static enum xprt_stat -svcudp_stat (xprt) - SVCXPRT *xprt attribute_unused; +svcudp_stat (SVCXPRT *xprt attribute_unused) { return XPRT_IDLE; } static bool_t -svcudp_recv (xprt, msg) - SVCXPRT *xprt; - struct rpc_msg *msg; +svcudp_recv (SVCXPRT *xprt, struct rpc_msg *msg) { struct svcudp_data *su = su_data (xprt); XDR *xdrs = &(su->su_xdrs); @@ -322,9 +274,7 @@ again: } static bool_t -svcudp_reply (xprt, msg) - SVCXPRT *xprt; - struct rpc_msg *msg; +svcudp_reply (SVCXPRT *xprt, struct rpc_msg *msg) { struct svcudp_data *su = su_data (xprt); XDR *xdrs = &(su->su_xdrs); @@ -368,20 +318,14 @@ svcudp_reply (xprt, msg) } static bool_t -svcudp_getargs (xprt, xdr_args, args_ptr) - SVCXPRT *xprt; - xdrproc_t xdr_args; - caddr_t args_ptr; +svcudp_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) { return (*xdr_args) (&(su_data (xprt)->su_xdrs), args_ptr); } static bool_t -svcudp_freeargs (xprt, xdr_args, args_ptr) - SVCXPRT *xprt; - xdrproc_t xdr_args; - caddr_t args_ptr; +svcudp_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) { XDR *xdrs = &(su_data (xprt)->su_xdrs); @@ -390,8 +334,7 @@ svcudp_freeargs (xprt, xdr_args, args_ptr) } static void -svcudp_destroy (xprt) - SVCXPRT *xprt; +svcudp_destroy (SVCXPRT *xprt) { struct svcudp_data *su = su_data (xprt); @@ -414,16 +357,8 @@ svcudp_destroy (xprt) #define SPARSENESS 4 /* 75% sparse */ -#ifdef USE_IN_LIBIO -# define CACHE_PERROR(msg) \ - if (_IO_fwide (stderr, 0) > 0) \ - (void) __fwprintf(stderr, L"%s\n", msg); \ - else \ - (void) fprintf(stderr, "%s\n", msg) -#else -# define CACHE_PERROR(msg) \ +#define CACHE_PERROR(msg) \ (void) fprintf(stderr,"%s\n", msg) -#endif #define ALLOC(type, size) \ (type *) mem_alloc((unsigned) (sizeof(type) * (size))) @@ -597,11 +532,7 @@ cache_set (SVCXPRT *xprt, u_long replylen) * return 1 if found, 0 if not found */ static int -cache_get (xprt, msg, replyp, replylenp) - SVCXPRT *xprt; - struct rpc_msg *msg; - char **replyp; - u_long *replylenp; +cache_get (SVCXPRT *xprt, struct rpc_msg *msg, char **replyp, u_long *replylenp) { u_int loc; cache_ptr ent; diff --git a/libc/inet/rpc/svc_unix.c b/libc/inet/rpc/svc_unix.c index 2d7790450..7a09af6a1 100644 --- a/libc/inet/rpc/svc_unix.c +++ b/libc/inet/rpc/svc_unix.c @@ -37,13 +37,10 @@ * and a record/unix stream. */ -#define __FORCE_GLIBC -#include <features.h> - #include <stdio.h> #include <unistd.h> #include <string.h> -#include <rpc/rpc.h> +#include "rpc_private.h" #include <rpc/svc.h> #include <sys/socket.h> #include <sys/uio.h> @@ -51,38 +48,6 @@ #include <errno.h> #include <stdlib.h> -#ifdef USE_IN_LIBIO -# include <wchar.h> -#endif - -/* Experimentally off - libc_hidden_proto(memcpy) */ -/* Experimentally off - libc_hidden_proto(memset) */ -/* Experimentally off - libc_hidden_proto(strlen) */ -libc_hidden_proto(socket) -libc_hidden_proto(close) -libc_hidden_proto(perror) -libc_hidden_proto(getpid) -libc_hidden_proto(xdrrec_create) -libc_hidden_proto(xdrrec_endofrecord) -libc_hidden_proto(xdrrec_skiprecord) -libc_hidden_proto(xdrrec_eof) -libc_hidden_proto(xdr_callmsg) -libc_hidden_proto(xdr_replymsg) -libc_hidden_proto(xprt_register) -libc_hidden_proto(xprt_unregister) -libc_hidden_proto(getegid) -libc_hidden_proto(geteuid) -libc_hidden_proto(getsockname) -libc_hidden_proto(setsockopt) -libc_hidden_proto(bind) -libc_hidden_proto(recvmsg) -libc_hidden_proto(sendmsg) -libc_hidden_proto(poll) -libc_hidden_proto(accept) -libc_hidden_proto(listen) -libc_hidden_proto(fputs) -libc_hidden_proto(abort) - /* * Ops vector for AF_UNIX based rpc service handle */ @@ -203,12 +168,7 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); if (r == NULL || xprt == NULL) { -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", _("svcunix_create: out of memory\n")); - else -#endif - fputs (_("svcunix_create: out of memory\n"), stderr); + fputs (_("svcunix_create: out of memory\n"), stderr); mem_free (r, sizeof (*r)); mem_free (xprt, sizeof (SVCXPRT)); return NULL; @@ -248,13 +208,7 @@ makefd_xprt (int fd, u_int sendsize, u_int recvsize) cd = (struct unix_conn *) mem_alloc (sizeof (struct unix_conn)); if (xprt == (SVCXPRT *) NULL || cd == (struct unix_conn *) NULL) { -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) __fwprintf (stderr, L"%s", - _("svc_unix: makefd_xprt: out of memory\n")); - else -#endif - (void) fputs (_("svc_unix: makefd_xprt: out of memory\n"), stderr); + (void) fputs (_("svc_unix: makefd_xprt: out of memory\n"), stderr); mem_free (xprt, sizeof (SVCXPRT)); mem_free (cd, sizeof (struct unix_conn)); return NULL; diff --git a/libc/inet/rpc/xdr.c b/libc/inet/rpc/xdr.c index 54e716176..57d7dbd40 100644 --- a/libc/inet/rpc/xdr.c +++ b/libc/inet/rpc/xdr.c @@ -41,24 +41,14 @@ static char sccsid[] = "@(#)xdr.c 1.35 87/08/12"; * xdr. */ -#define __FORCE_GLIBC -#include <features.h> - #include <stdio.h> #include <limits.h> #include <string.h> +#include <libintl.h> #include <rpc/types.h> #include <rpc/xdr.h> -#ifdef USE_IN_LIBIO -# include <wchar.h> -libc_hidden_proto(fwprintf) -#endif - -/* Experimentally off - libc_hidden_proto(strlen) */ -libc_hidden_proto(fputs) - /* * constants specific to the xdr "protocol" */ @@ -87,7 +77,6 @@ xdr_free (xdrproc_t proc, char *objp) /* * XDR nothing */ -libc_hidden_proto(xdr_void) bool_t xdr_void (void) { @@ -100,11 +89,9 @@ libc_hidden_def(xdr_void) * The definition of xdr_long() is kept for backward * compatibility. Instead xdr_int() should be used. */ -libc_hidden_proto(xdr_long) bool_t xdr_long (XDR *xdrs, long *lp) { - if (xdrs->x_op == XDR_ENCODE && (sizeof (int32_t) == sizeof (long) || (int32_t) *lp == *lp)) @@ -123,7 +110,6 @@ libc_hidden_def(xdr_long) /* * XDR short integers */ -libc_hidden_proto(xdr_short) bool_t xdr_short (XDR *xdrs, short *sp) { @@ -153,7 +139,6 @@ libc_hidden_def(xdr_short) /* * XDR integers */ -libc_hidden_proto(xdr_int) bool_t xdr_int (XDR *xdrs, int *ip) { @@ -192,7 +177,6 @@ libc_hidden_def(xdr_int) * The definition of xdr_u_long() is kept for backward * compatibility. Instead xdr_u_int() should be used. */ -libc_hidden_proto(xdr_u_long) bool_t xdr_u_long (XDR *xdrs, u_long *ulp) { @@ -226,7 +210,6 @@ libc_hidden_def(xdr_u_long) /* * XDR unsigned integers */ -libc_hidden_proto(xdr_u_int) bool_t xdr_u_int (XDR *xdrs, u_int *up) { @@ -237,10 +220,10 @@ xdr_u_int (XDR *xdrs, u_int *up) { case XDR_ENCODE: l = (u_long) * up; - return XDR_PUTLONG (xdrs, &l); + return XDR_PUTLONG (xdrs, (long *) &l); case XDR_DECODE: - if (!XDR_GETLONG (xdrs, &l)) + if (!XDR_GETLONG (xdrs, (long *) &l)) { return FALSE; } @@ -263,24 +246,24 @@ libc_hidden_def(xdr_u_int) * XDR hyper integers * same as xdr_u_hyper - open coded to save a proc call! */ -libc_hidden_proto(xdr_hyper) bool_t xdr_hyper (XDR *xdrs, quad_t *llp) { long t1; - unsigned long int t2; + unsigned long t2; if (xdrs->x_op == XDR_ENCODE) { t1 = (long) ((*llp) >> 32); t2 = (long) (*llp); - return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2)); + return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, (long *) &t2)); } if (xdrs->x_op == XDR_DECODE) { - if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2)) + if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, (long *) &t2)) return FALSE; + /* t2 must be unsigned for this to work */ *llp = ((quad_t) t1) << 32; *llp |= t2; return TRUE; @@ -298,7 +281,6 @@ libc_hidden_def(xdr_hyper) * XDR hyper integers * same as xdr_hyper - open coded to save a proc call! */ -libc_hidden_proto(xdr_u_hyper) bool_t xdr_u_hyper (XDR *xdrs, u_quad_t *ullp) { @@ -309,12 +291,12 @@ xdr_u_hyper (XDR *xdrs, u_quad_t *ullp) { t1 = (unsigned long) ((*ullp) >> 32); t2 = (unsigned long) (*ullp); - return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2)); + return (XDR_PUTLONG(xdrs, (long *) &t1) && XDR_PUTLONG(xdrs, (long *) &t2)); } if (xdrs->x_op == XDR_DECODE) { - if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2)) + if (!XDR_GETLONG(xdrs, (long *) &t1) || !XDR_GETLONG(xdrs, (long *) &t2)) return FALSE; *ullp = ((u_quad_t) t1) << 32; *ullp |= t2; @@ -343,7 +325,6 @@ xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp) /* * XDR unsigned short integers */ -libc_hidden_proto(xdr_u_short) bool_t xdr_u_short (XDR *xdrs, u_short *usp) { @@ -353,10 +334,10 @@ xdr_u_short (XDR *xdrs, u_short *usp) { case XDR_ENCODE: l = (u_long) * usp; - return XDR_PUTLONG (xdrs, &l); + return XDR_PUTLONG (xdrs, (long *) &l); case XDR_DECODE: - if (!XDR_GETLONG (xdrs, &l)) + if (!XDR_GETLONG (xdrs, (long *) &l)) { return FALSE; } @@ -408,7 +389,6 @@ xdr_u_char (XDR *xdrs, u_char *cp) /* * XDR booleans */ -libc_hidden_proto(xdr_bool) bool_t xdr_bool (XDR *xdrs, bool_t *bp) { @@ -438,7 +418,6 @@ libc_hidden_def(xdr_bool) /* * XDR enumerations */ -libc_hidden_proto(xdr_enum) bool_t xdr_enum (XDR *xdrs, enum_t *ep) { @@ -492,7 +471,6 @@ libc_hidden_def(xdr_enum) * Allows the specification of a fixed size sequence of opaque bytes. * cp points to the opaque object and cnt gives the byte length. */ -libc_hidden_proto(xdr_opaque) bool_t xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt) { @@ -544,7 +522,6 @@ libc_hidden_def(xdr_opaque) * *cpp is a pointer to the bytes, *sizep is the count. * If *cpp is NULL maxsize bytes are allocated */ -libc_hidden_proto(xdr_bytes) bool_t xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) { @@ -580,12 +557,7 @@ xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) } if (sp == NULL) { -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", _("xdr_bytes: out of memory\n")); - else -#endif - (void) fputs (_("xdr_bytes: out of memory\n"), stderr); + (void) fputs (_("xdr_bytes: out of memory\n"), stderr); return FALSE; } /* fall into ... */ @@ -609,9 +581,7 @@ libc_hidden_def(xdr_bytes) * Implemented here due to commonality of the object. */ bool_t -xdr_netobj (xdrs, np) - XDR *xdrs; - struct netobj *np; +xdr_netobj (XDR *xdrs, struct netobj *np) { return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ); @@ -628,7 +598,6 @@ xdr_netobj (xdrs, np) * routine may be called. * If there is no specific or default routine an error is returned. */ -libc_hidden_proto(xdr_union) bool_t xdr_union (XDR *xdrs, enum_t *dscmp, char *unp, const struct xdr_discrim *choices, xdrproc_t dfault) { @@ -675,7 +644,6 @@ libc_hidden_def(xdr_union) * storage is allocated. The last parameter is the max allowed length * of the string as specified by a protocol. */ -libc_hidden_proto(xdr_string) bool_t xdr_string (XDR *xdrs, char **cpp, u_int maxsize) { @@ -726,13 +694,7 @@ xdr_string (XDR *xdrs, char **cpp, u_int maxsize) *cpp = sp = (char *) mem_alloc (nodesize); if (sp == NULL) { -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", - _("xdr_string: out of memory\n")); - else -#endif - (void) fputs (_("xdr_string: out of memory\n"), stderr); + (void) fputs (_("xdr_string: out of memory\n"), stderr); return FALSE; } sp[size] = 0; @@ -755,9 +717,7 @@ libc_hidden_def(xdr_string) * routines like clnt_call */ bool_t -xdr_wrapstring (xdrs, cpp) - XDR *xdrs; - char **cpp; +xdr_wrapstring (XDR *xdrs, char **cpp) { if (xdr_string (xdrs, cpp, LASTUNSIGNED)) { diff --git a/libc/inet/rpc/xdr_array.c b/libc/inet/rpc/xdr_array.c index a2299b683..25428aac3 100644 --- a/libc/inet/rpc/xdr_array.c +++ b/libc/inet/rpc/xdr_array.c @@ -40,27 +40,15 @@ static char sccsid[] = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro"; * arrays. See xdr.h for more info on the interface to xdr. */ -#define __FORCE_GLIBC -#include <features.h> - #include <stdio.h> #include <string.h> #include <rpc/types.h> #include <rpc/xdr.h> #include <limits.h> - -#ifdef USE_IN_LIBIO -# include <wchar.h> -libc_hidden_proto(fwprintf) -#endif - -/* Experimentally off - libc_hidden_proto(memset) */ -libc_hidden_proto(fputs) -libc_hidden_proto(xdr_u_int) +#include <libintl.h> #define LASTUNSIGNED ((u_int)0-1) - /* * XDR an array of arbitrary elements * *addrp is a pointer to the array, *sizep is the number of elements. @@ -68,7 +56,6 @@ libc_hidden_proto(xdr_u_int) * elsize is the size (in bytes) of each element, and elproc is the * xdr procedure to call to handle each element of the array. */ -libc_hidden_proto(xdr_array) bool_t xdr_array (XDR *xdrs, caddr_t *addrp, u_int *sizep, u_int maxsize, u_int elsize, xdrproc_t elproc) { @@ -107,13 +94,7 @@ xdr_array (XDR *xdrs, caddr_t *addrp, u_int *sizep, u_int maxsize, u_int elsize, *addrp = target = mem_alloc (nodesize); if (target == NULL) { -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", - _("xdr_array: out of memory\n")); - else -#endif - (void) fputs (_("xdr_array: out of memory\n"), stderr); + (void) fputs (_("xdr_array: out of memory\n"), stderr); return FALSE; } memset (target, 0, nodesize); @@ -157,12 +138,8 @@ libc_hidden_def(xdr_array) * > xdr_elem: routine to XDR each element */ bool_t -xdr_vector (xdrs, basep, nelem, elemsize, xdr_elem) - XDR *xdrs; - char *basep; - u_int nelem; - u_int elemsize; - xdrproc_t xdr_elem; +xdr_vector (XDR *xdrs, char *basep, u_int nelem, u_int elemsize, + xdrproc_t xdr_elem) { u_int i; char *elptr; diff --git a/libc/inet/rpc/xdr_float.c b/libc/inet/rpc/xdr_float.c index 03632c5ca..f8a2bb399 100644 --- a/libc/inet/rpc/xdr_float.c +++ b/libc/inet/rpc/xdr_float.c @@ -41,9 +41,6 @@ static char sccsid[] = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro"; * xdr. */ -#define __FORCE_GLIBC -#include <features.h> - #include <stdio.h> #include <endian.h> @@ -57,69 +54,12 @@ static char sccsid[] = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro"; #define LSW (__FLOAT_WORD_ORDER == __BIG_ENDIAN) -#ifdef vax - -/* What IEEE single precision floating point looks like on a Vax */ -struct ieee_single { - unsigned int mantissa: 23; - unsigned int exp : 8; - unsigned int sign : 1; -}; - -/* Vax single precision floating point */ -struct vax_single { - unsigned int mantissa1 : 7; - unsigned int exp : 8; - unsigned int sign : 1; - unsigned int mantissa2 : 16; -}; - -#define VAX_SNG_BIAS 0x81 -#define IEEE_SNG_BIAS 0x7f - -static struct sgl_limits { - struct vax_single s; - struct ieee_single ieee; -} sgl_limits[2] = { - {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ - { 0x0, 0xff, 0x0 }}, /* Max IEEE */ - {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ - { 0x0, 0x0, 0x0 }} /* Min IEEE */ -}; -#endif /* vax */ - bool_t -xdr_float(xdrs, fp) - XDR *xdrs; - float *fp; +xdr_float(XDR *xdrs, float *fp) { -#ifdef vax - struct ieee_single is; - struct vax_single vs, *vsp; - struct sgl_limits *lim; - int i; -#endif switch (xdrs->x_op) { case XDR_ENCODE: -#ifdef vax - vs = *((struct vax_single *)fp); - for (i = 0, lim = sgl_limits; - i < sizeof(sgl_limits)/sizeof(struct sgl_limits); - i++, lim++) { - if ((vs.mantissa2 == lim->s.mantissa2) && - (vs.exp == lim->s.exp) && - (vs.mantissa1 == lim->s.mantissa1)) { - is = lim->ieee; - goto shipit; - } - } - is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; - is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; - shipit: - is.sign = vs.sign; - return (XDR_PUTLONG(xdrs, (long *)&is)); -#else if (sizeof(float) == sizeof(long)) return (XDR_PUTLONG(xdrs, (long *)fp)); else if (sizeof(float) == sizeof(int)) { @@ -127,29 +67,8 @@ xdr_float(xdrs, fp) return (XDR_PUTLONG(xdrs, &tmp)); } break; -#endif case XDR_DECODE: -#ifdef vax - vsp = (struct vax_single *)fp; - if (!XDR_GETLONG(xdrs, (long *)&is)) - return (FALSE); - for (i = 0, lim = sgl_limits; - i < sizeof(sgl_limits)/sizeof(struct sgl_limits); - i++, lim++) { - if ((is.exp == lim->ieee.exp) && - (is.mantissa == lim->ieee.mantissa)) { - *vsp = lim->s; - goto doneit; - } - } - vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; - vsp->mantissa2 = is.mantissa; - vsp->mantissa1 = (is.mantissa >> 16); - doneit: - vsp->sign = is.sign; - return (TRUE); -#else if (sizeof(float) == sizeof(long)) return (XDR_GETLONG(xdrs, (long *)fp)); else if (sizeof(float) == sizeof(int)) { @@ -160,7 +79,6 @@ xdr_float(xdrs, fp) } } break; -#endif case XDR_FREE: return (TRUE); @@ -168,84 +86,13 @@ xdr_float(xdrs, fp) return (FALSE); } -/* - * This routine works on Suns (Sky / 68000's) and Vaxen. - */ - -#ifdef vax -/* What IEEE double precision floating point looks like on a Vax */ -struct ieee_double { - unsigned int mantissa1 : 20; - unsigned int exp : 11; - unsigned int sign : 1; - unsigned int mantissa2 : 32; -}; - -/* Vax double precision floating point */ -struct vax_double { - unsigned int mantissa1 : 7; - unsigned int exp : 8; - unsigned int sign : 1; - unsigned int mantissa2 : 16; - unsigned int mantissa3 : 16; - unsigned int mantissa4 : 16; -}; - -#define VAX_DBL_BIAS 0x81 -#define IEEE_DBL_BIAS 0x3ff -#define MASK(nbits) ((1 << nbits) - 1) - -static struct dbl_limits { - struct vax_double d; - struct ieee_double ieee; -} dbl_limits[2] = { - {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ - { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ - {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ - { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ -}; - -#endif /* vax */ - - bool_t -xdr_double(xdrs, dp) - XDR *xdrs; - double *dp; +xdr_double(XDR *xdrs, double *dp) { -#ifdef vax - struct ieee_double id; - struct vax_double vd; - register struct dbl_limits *lim; - int i; -#endif switch (xdrs->x_op) { case XDR_ENCODE: -#ifdef vax - vd = *((struct vax_double *)dp); - for (i = 0, lim = dbl_limits; - i < sizeof(dbl_limits)/sizeof(struct dbl_limits); - i++, lim++) { - if ((vd.mantissa4 == lim->d.mantissa4) && - (vd.mantissa3 == lim->d.mantissa3) && - (vd.mantissa2 == lim->d.mantissa2) && - (vd.mantissa1 == lim->d.mantissa1) && - (vd.exp == lim->d.exp)) { - id = lim->ieee; - goto shipit; - } - } - id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; - id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); - id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | - (vd.mantissa3 << 13) | - ((vd.mantissa4 >> 3) & MASK(13)); - shipit: - id.sign = vd.sign; - dp = (double *)&id; -#endif if (2*sizeof(long) == sizeof(double)) { long *lp = (long *)dp; return (XDR_PUTLONG(xdrs, lp+!LSW) && @@ -261,31 +108,6 @@ xdr_double(xdrs, dp) break; case XDR_DECODE: -#ifdef vax - lp = (long *)&id; - if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp)) - return (FALSE); - for (i = 0, lim = dbl_limits; - i < sizeof(dbl_limits)/sizeof(struct dbl_limits); - i++, lim++) { - if ((id.mantissa2 == lim->ieee.mantissa2) && - (id.mantissa1 == lim->ieee.mantissa1) && - (id.exp == lim->ieee.exp)) { - vd = lim->d; - goto doneit; - } - } - vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; - vd.mantissa1 = (id.mantissa1 >> 13); - vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | - (id.mantissa2 >> 29); - vd.mantissa3 = (id.mantissa2 >> 13); - vd.mantissa4 = (id.mantissa2 << 3); - doneit: - vd.sign = id.sign; - *dp = *((double *)&vd); - return (TRUE); -#else if (2*sizeof(long) == sizeof(double)) { long *lp = (long *)dp; return (XDR_GETLONG(xdrs, lp+!LSW) && @@ -301,7 +123,6 @@ xdr_double(xdrs, dp) } } break; -#endif case XDR_FREE: return (TRUE); diff --git a/libc/inet/rpc/xdr_intXX_t.c b/libc/inet/rpc/xdr_intXX_t.c index d36d1623b..0688b3fc3 100644 --- a/libc/inet/rpc/xdr_intXX_t.c +++ b/libc/inet/rpc/xdr_intXX_t.c @@ -13,9 +13,8 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <rpc/types.h> #include <rpc/xdr.h> @@ -34,9 +33,9 @@ xdr_int64_t (XDR *xdrs, int64_t *ip) case XDR_ENCODE: t1 = (int32_t) ((*ip) >> 32); t2 = (int32_t) (*ip); - return (XDR_PUTINT32(xdrs, &t1) && XDR_PUTINT32(xdrs, &t2)); + return (XDR_PUTINT32(xdrs, &t1) && XDR_PUTINT32(xdrs, (int32_t *) &t2)); case XDR_DECODE: - if (!XDR_GETINT32(xdrs, &t1) || !XDR_GETINT32(xdrs, &t2)) + if (!XDR_GETINT32(xdrs, &t1) || !XDR_GETINT32(xdrs, (int32_t *) &t2)) return FALSE; *ip = ((int64_t) t1) << 32; *ip |= t2; @@ -47,6 +46,7 @@ xdr_int64_t (XDR *xdrs, int64_t *ip) return FALSE; } } +strong_alias_untyped(xdr_int64_t,xdr_quad_t) /* XDR 64bit unsigned integers */ bool_t @@ -75,6 +75,7 @@ xdr_uint64_t (XDR *xdrs, uint64_t *uip) return FALSE; } } +strong_alias_untyped(xdr_uint64_t,xdr_u_quad_t) /* XDR 32bit integers */ bool_t diff --git a/libc/inet/rpc/xdr_mem.c b/libc/inet/rpc/xdr_mem.c index b7410c404..6773b56e2 100644 --- a/libc/inet/rpc/xdr_mem.c +++ b/libc/inet/rpc/xdr_mem.c @@ -43,7 +43,6 @@ #include <limits.h> #include <rpc/rpc.h> -/* Experimentally off - libc_hidden_proto(memcpy) */ static bool_t xdrmem_getlong (XDR *, long *); static bool_t xdrmem_putlong (XDR *, const long *); @@ -74,14 +73,11 @@ static const struct xdr_ops xdrmem_ops = * The procedure xdrmem_create initializes a stream descriptor for a * memory buffer. */ -libc_hidden_proto(xdrmem_create) void xdrmem_create (XDR *xdrs, const caddr_t addr, u_int size, enum xdr_op op) { xdrs->x_op = op; - /* We have to add the const since the `struct xdr_ops' in `struct XDR' - is not `const'. */ - xdrs->x_ops = (struct xdr_ops *) &xdrmem_ops; + xdrs->x_ops = &xdrmem_ops; xdrs->x_private = xdrs->x_base = addr; xdrs->x_handy = size; } @@ -175,9 +171,7 @@ xdrmem_getpos (const XDR *xdrs) * xdrs modified */ static bool_t -xdrmem_setpos (xdrs, pos) - XDR *xdrs; - u_int pos; +xdrmem_setpos (XDR *xdrs, u_int pos) { caddr_t newaddr = xdrs->x_base + pos; caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; diff --git a/libc/inet/rpc/xdr_rec.c b/libc/inet/rpc/xdr_rec.c index ac331c4d3..3ad7d7275 100644 --- a/libc/inet/rpc/xdr_rec.c +++ b/libc/inet/rpc/xdr_rec.c @@ -44,40 +44,32 @@ * The other 31 bits encode the byte length of the fragment. */ -#define __FORCE_GLIBC -#include <features.h> - - #include <stdio.h> #include <string.h> #include <unistd.h> -#include <rpc/rpc.h> - -#ifdef USE_IN_LIBIO -# include <wchar.h> -# include <libio/iolibio.h> -# define fputs(s, f) _IO_fputs (s, f) -libc_hidden_proto(fwprintf) -#endif - -/* Experimentally off - libc_hidden_proto(memcpy) */ -libc_hidden_proto(fputs) -libc_hidden_proto(lseek) +#include "rpc_private.h" -static bool_t xdrrec_getlong (XDR *, long *); -static bool_t xdrrec_putlong (XDR *, const long *); static bool_t xdrrec_getbytes (XDR *, caddr_t, u_int); static bool_t xdrrec_putbytes (XDR *, const char *, u_int); +static bool_t xdrrec_getint32 (XDR *, int32_t *); +static bool_t xdrrec_putint32 (XDR *, const int32_t *); +#if ULONG_MAX != 0xffffffff +static bool_t xdrrec_getlong (XDR *, long *); +static bool_t xdrrec_putlong (XDR *, const long *); +#endif static u_int xdrrec_getpos (const XDR *); static bool_t xdrrec_setpos (XDR *, u_int); static int32_t *xdrrec_inline (XDR *, u_int); static void xdrrec_destroy (XDR *); -static bool_t xdrrec_getint32 (XDR *, int32_t *); -static bool_t xdrrec_putint32 (XDR *, const int32_t *); static const struct xdr_ops xdrrec_ops = { +#if ULONG_MAX == 0xffffffff + (bool_t (*)(XDR *, long *)) xdrrec_getint32, + (bool_t (*)(XDR *, const long *)) xdrrec_putint32, +#else xdrrec_getlong, xdrrec_putlong, +#endif xdrrec_getbytes, xdrrec_putbytes, xdrrec_getpos, @@ -146,7 +138,6 @@ static bool_t get_input_bytes (RECSTREAM *, caddr_t, int) internal_function; * write respectively. They are like the system * calls expect that they take an opaque handle rather than an fd. */ -libc_hidden_proto(xdrrec_create) void xdrrec_create (XDR *xdrs, u_int sendsize, u_int recvsize, caddr_t tcp_handle, @@ -163,12 +154,7 @@ xdrrec_create (XDR *xdrs, u_int sendsize, if (rstrm == NULL || buf == NULL) { -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", _("xdrrec_create: out of memory\n")); - else -#endif - (void) fputs (_("xdrrec_create: out of memory\n"), stderr); + (void) fputs (_("xdrrec_create: out of memory\n"), stderr); mem_free (rstrm, sizeof (RECSTREAM)); mem_free (buf, sendsize + recvsize + BYTES_PER_XDR_UNIT); /* @@ -191,9 +177,7 @@ xdrrec_create (XDR *xdrs, u_int sendsize, /* * now the rest ... */ - /* We have to add the const since the `struct xdr_ops' in `struct XDR' - is not `const'. */ - xdrs->x_ops = (struct xdr_ops *) &xdrrec_ops; + xdrs->x_ops = &xdrrec_ops; xdrs->x_private = (caddr_t) rstrm; rstrm->tcp_handle = tcp_handle; rstrm->readit = readit; @@ -218,35 +202,46 @@ libc_hidden_def(xdrrec_create) */ static bool_t -xdrrec_getlong (XDR *xdrs, long *lp) +xdrrec_getint32 (XDR *xdrs, int32_t *ip) { RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; - int32_t *buflp = (int32_t *) rstrm->in_finger; + int32_t *bufip = (int32_t *) rstrm->in_finger; int32_t mylong; /* first try the inline, fast case */ if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT && - rstrm->in_boundry - (char *) buflp >= BYTES_PER_XDR_UNIT) + rstrm->in_boundry - (char *) bufip >= BYTES_PER_XDR_UNIT) { - *lp = (int32_t) ntohl (*buflp); + *ip = ntohl (*bufip); rstrm->fbtbc -= BYTES_PER_XDR_UNIT; rstrm->in_finger += BYTES_PER_XDR_UNIT; } else { - if (!xdrrec_getbytes (xdrs, (caddr_t) & mylong, + if (!xdrrec_getbytes (xdrs, (caddr_t) &mylong, BYTES_PER_XDR_UNIT)) return FALSE; - *lp = (int32_t) ntohl (mylong); + *ip = ntohl (mylong); } return TRUE; } +#if ULONG_MAX != 0xffffffff static bool_t -xdrrec_putlong (XDR *xdrs, const long *lp) +xdrrec_getlong (XDR *xdrs, long *lp) +{ + int32_t v; + bool_t r = xdrrec_getint32 (xdrs, &v); + *lp = v; + return r; +} +#endif + +static bool_t +xdrrec_putint32 (XDR *xdrs, const int32_t *ip) { RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; - int32_t *dest_lp = (int32_t *) rstrm->out_finger; + int32_t *dest_ip = (int32_t *) rstrm->out_finger; if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry) { @@ -258,13 +253,22 @@ xdrrec_putlong (XDR *xdrs, const long *lp) rstrm->frag_sent = TRUE; if (!flush_out (rstrm, FALSE)) return FALSE; - dest_lp = (int32_t *) rstrm->out_finger; + dest_ip = (int32_t *) rstrm->out_finger; rstrm->out_finger += BYTES_PER_XDR_UNIT; } - *dest_lp = htonl (*lp); + *dest_ip = htonl (*ip); return TRUE; } +#if ULONG_MAX != 0xffffffff +static bool_t +xdrrec_putlong (XDR *xdrs, const long *lp) +{ + int32_t v = *lp; + return xdrrec_putint32 (xdrs, &v); +} +#endif + static bool_t /* must manage buffers, fragments, and records */ xdrrec_getbytes (XDR *xdrs, caddr_t addr, u_int len) { @@ -425,54 +429,6 @@ xdrrec_destroy (XDR *xdrs) mem_free ((caddr_t) rstrm, sizeof (RECSTREAM)); } -static bool_t -xdrrec_getint32 (XDR *xdrs, int32_t *ip) -{ - RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; - int32_t *bufip = (int32_t *) rstrm->in_finger; - int32_t mylong; - - /* first try the inline, fast case */ - if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT && - rstrm->in_boundry - (char *) bufip >= BYTES_PER_XDR_UNIT) - { - *ip = ntohl (*bufip); - rstrm->fbtbc -= BYTES_PER_XDR_UNIT; - rstrm->in_finger += BYTES_PER_XDR_UNIT; - } - else - { - if (!xdrrec_getbytes (xdrs, (caddr_t) &mylong, - BYTES_PER_XDR_UNIT)) - return FALSE; - *ip = ntohl (mylong); - } - return TRUE; -} - -static bool_t -xdrrec_putint32 (XDR *xdrs, const int32_t *ip) -{ - RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; - int32_t *dest_ip = (int32_t *) rstrm->out_finger; - - if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry) - { - /* - * this case should almost never happen so the code is - * inefficient - */ - rstrm->out_finger -= BYTES_PER_XDR_UNIT; - rstrm->frag_sent = TRUE; - if (!flush_out (rstrm, FALSE)) - return FALSE; - dest_ip = (int32_t *) rstrm->out_finger; - rstrm->out_finger += BYTES_PER_XDR_UNIT; - } - *dest_ip = htonl (*ip); - return TRUE; -} - /* * Exported routines to manage xdr records */ @@ -481,7 +437,6 @@ xdrrec_putint32 (XDR *xdrs, const int32_t *ip) * Before reading (deserializing from the stream, one should always call * this procedure to guarantee proper record alignment. */ -libc_hidden_proto(xdrrec_skiprecord) bool_t xdrrec_skiprecord (XDR *xdrs) { @@ -505,7 +460,6 @@ libc_hidden_def(xdrrec_skiprecord) * Returns TRUE iff there is no more input in the buffer * after consuming the rest of the current record. */ -libc_hidden_proto(xdrrec_eof) bool_t xdrrec_eof (XDR *xdrs) { @@ -531,7 +485,6 @@ libc_hidden_def(xdrrec_eof) * (output) tcp stream. (This lets the package support batched or * pipelined procedure calls.) TRUE => immediate flush to tcp connection. */ -libc_hidden_proto(xdrrec_endofrecord) bool_t xdrrec_endofrecord (XDR *xdrs, bool_t sendnow) { diff --git a/libc/inet/rpc/xdr_reference.c b/libc/inet/rpc/xdr_reference.c index 6282f9cb1..85765886b 100644 --- a/libc/inet/rpc/xdr_reference.c +++ b/libc/inet/rpc/xdr_reference.c @@ -40,24 +40,11 @@ static char sccsid[] = "@(#)xdr_reference.c 1.11 87/08/11 SMI"; * "pointers". See xdr.h for more info on the interface to xdr. */ -#define __FORCE_GLIBC -#include <features.h> - #include <stdio.h> #include <string.h> #include <rpc/types.h> #include <rpc/xdr.h> - -#ifdef USE_IN_LIBIO -# include <wchar.h> -# include <libio/iolibio.h> -# define fputs(s, f) _IO_fputs (s, f) -libc_hidden_proto(fwprintf) -#endif - -/* Experimentally off - libc_hidden_proto(memset) */ -libc_hidden_proto(xdr_bool) -libc_hidden_proto(fputs) +#include <libintl.h> #define LASTUNSIGNED ((u_int)0-1) @@ -70,7 +57,6 @@ libc_hidden_proto(fputs) * size is the size of the referneced structure. * proc is the routine to handle the referenced structure. */ -libc_hidden_proto(xdr_reference) bool_t xdr_reference (XDR *xdrs, caddr_t *pp, u_int size, xdrproc_t proc) { @@ -87,13 +73,7 @@ xdr_reference (XDR *xdrs, caddr_t *pp, u_int size, xdrproc_t proc) *pp = loc = (caddr_t) mem_alloc (size); if (loc == NULL) { -#ifdef USE_IN_LIBIO - if (_IO_fwide (stderr, 0) > 0) - (void) fwprintf (stderr, L"%s", - _("xdr_reference: out of memory\n")); - else -#endif - (void) fputs (_("xdr_reference: out of memory\n"), stderr); + (void) fputs (_("xdr_reference: out of memory\n"), stderr); return FALSE; } memset (loc, 0, (int) size); @@ -133,11 +113,7 @@ libc_hidden_def(xdr_reference) * */ bool_t -xdr_pointer (xdrs, objpp, obj_size, xdr_obj) - XDR *xdrs; - char **objpp; - u_int obj_size; - xdrproc_t xdr_obj; +xdr_pointer (XDR *xdrs, char **objpp, u_int obj_size, xdrproc_t xdr_obj) { bool_t more_data; diff --git a/libc/inet/rpc/xdr_stdio.c b/libc/inet/rpc/xdr_stdio.c index 32689e132..6a18fce08 100644 --- a/libc/inet/rpc/xdr_stdio.c +++ b/libc/inet/rpc/xdr_stdio.c @@ -41,20 +41,6 @@ #include <stdio.h> #include <rpc/xdr.h> -#ifdef USE_IN_LIBIO -# include <libio/iolibio.h> -# define fflush(s) _IO_fflush (s) -# define fread(p, m, n, s) _IO_fread (p, m, n, s) -# define ftell(s) _IO_ftell (s) -# define fwrite(p, m, n, s) _IO_fwrite (p, m, n, s) -#endif - -libc_hidden_proto(fread) -libc_hidden_proto(fwrite) -libc_hidden_proto(fseek) -libc_hidden_proto(fflush) -libc_hidden_proto(ftell) - static bool_t xdrstdio_getlong (XDR *, long *); static bool_t xdrstdio_putlong (XDR *, const long *); static bool_t xdrstdio_getbytes (XDR *, caddr_t, u_int); @@ -92,9 +78,7 @@ void xdrstdio_create (XDR *xdrs, FILE *file, enum xdr_op op) { xdrs->x_op = op; - /* We have to add the const since the `struct xdr_ops' in `struct XDR' - is not `const'. */ - xdrs->x_ops = (struct xdr_ops *) &xdrstdio_ops; + xdrs->x_ops = &xdrstdio_ops; xdrs->x_private = (caddr_t) file; xdrs->x_handy = 0; xdrs->x_base = 0; diff --git a/libc/inet/socketcalls.c b/libc/inet/socketcalls.c index ca93f6a18..1fef8100b 100644 --- a/libc/inet/socketcalls.c +++ b/libc/inet/socketcalls.c @@ -4,15 +4,12 @@ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ -#define __FORCE_GLIBC -#include <features.h> -#include <errno.h> -#include <syscall.h> +#include <stddef.h> +#include <sys/syscall.h> #include <sys/socket.h> +#include <cancel.h> #ifdef __NR_socketcall -extern int __socketcall(int call, unsigned long *args) attribute_hidden; - /* Various socketcall numbers */ #define SYS_SOCKET 1 #define SYS_BIND 2 @@ -31,110 +28,167 @@ extern int __socketcall(int call, unsigned long *args) attribute_hidden; #define SYS_GETSOCKOPT 15 #define SYS_SENDMSG 16 #define SYS_RECVMSG 17 +#define SYS_ACCEPT4 18 +#endif + +/* exposed on x86 since Linux commit 9dea5dc921b5f4045a18c63eb92e84dc274d17eb */ +#if defined(__sparc__) || defined(__i386__) +#undef __NR_accept +#undef __NR_accept4 +#undef __NR_bind +#undef __NR_connect +#undef __NR_getpeername +#undef __NR_getsockname +#undef __NR_getsockopt +#undef __NR_listen +#undef __NR_recv +#undef __NR_recvfrom +#undef __NR_recvmsg +#undef __NR_send +#undef __NR_sendmsg +#undef __NR_sendto +#undef __NR_setsockopt +#undef __NR_shutdown +#undef __NR_socket +#undef __NR_socketpair #endif - #ifdef L_accept -extern __typeof(accept) __libc_accept; -#ifdef __NR_accept -#define __NR___libc_accept __NR_accept -_syscall3(int, __libc_accept, int, call, struct sockaddr *, addr, socklen_t *,addrlen); -#elif defined(__NR_socketcall) -int __libc_accept(int s, struct sockaddr *addr, socklen_t * addrlen) +static int __NC(accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { +# ifdef __NR_accept + return INLINE_SYSCALL(accept, 3, sockfd, addr, addrlen); +# else unsigned long args[3]; - args[0] = s; + args[0] = sockfd; args[1] = (unsigned long) addr; args[2] = (unsigned long) addrlen; + return __socketcall(SYS_ACCEPT, args); +# endif +} +CANCELLABLE_SYSCALL(int, accept, (int sockfd, struct sockaddr *addr, socklen_t *addrlen), + (sockfd, addr, addrlen)) +lt_libc_hidden(accept) +#endif + +#ifdef L_accept4 +#ifdef __NR_accept4 +# define __NR___sys_accept4 __NR_accept4 +static _syscall4(int, __sys_accept4, int, fd, struct sockaddr *, addr, socklen_t *, addrlen, int, flags) +int accept4(int fd, struct sockaddr *addr, socklen_t * addrlen, int flags) +{ + if (SINGLE_THREAD_P) + return __sys_accept4(fd, addr, addrlen, flags); +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + else { + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __sys_accept4(fd, addr, addrlen, flags); + LIBC_CANCEL_RESET (oldtype); + return result; + } +#endif +} +#elif defined(__NR_socketcall) +int accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) +{ + unsigned long args[4]; + + args[0] = fd; + args[1] = (unsigned long) addr; + args[2] = (unsigned long) addrlen; + args[3] = flags; + if (SINGLE_THREAD_P) + return __socketcall(SYS_ACCEPT4, args); +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + else { + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __socketcall(SYS_ACCEPT4, args); + LIBC_CANCEL_RESET (oldtype); + return result; + } +#endif } #endif -libc_hidden_proto(accept) -weak_alias(__libc_accept,accept) -libc_hidden_weak(accept) #endif #ifdef L_bind -libc_hidden_proto(bind) -#ifdef __NR_bind -_syscall3(int, bind, int, sockfd, const struct sockaddr *, myaddr, socklen_t, addrlen); -#elif defined(__NR_socketcall) int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen) { +# ifdef __NR_bind + return INLINE_SYSCALL(bind, 3, sockfd, myaddr, addrlen); +# else unsigned long args[3]; args[0] = sockfd; args[1] = (unsigned long) myaddr; args[2] = addrlen; return __socketcall(SYS_BIND, args); +# endif } -#endif libc_hidden_def(bind) #endif #ifdef L_connect -extern __typeof(connect) __libc_connect; -#ifdef __NR_connect -#define __NR___libc_connect __NR_connect -_syscall3(int, __libc_connect, int, sockfd, const struct sockaddr *, saddr, socklen_t, addrlen); -#elif defined(__NR_socketcall) -int __libc_connect(int sockfd, const struct sockaddr *saddr, socklen_t addrlen) +static int __NC(connect)(int sockfd, const struct sockaddr *saddr, socklen_t addrlen) { +# ifdef __NR_connect + return INLINE_SYSCALL(connect, 3, sockfd, saddr, addrlen); +# else unsigned long args[3]; args[0] = sockfd; args[1] = (unsigned long) saddr; args[2] = addrlen; return __socketcall(SYS_CONNECT, args); +# endif } -#endif -libc_hidden_proto(connect) -weak_alias(__libc_connect,connect) -libc_hidden_weak(connect) +CANCELLABLE_SYSCALL(int, connect, (int sockfd, const struct sockaddr *saddr, socklen_t addrlen), + (sockfd, saddr, addrlen)) +lt_libc_hidden(connect) #endif #ifdef L_getpeername -#ifdef __NR_getpeername -_syscall3(int, getpeername, int, sockfd, struct sockaddr *, addr, socklen_t *,paddrlen); -#elif defined(__NR_socketcall) -int getpeername(int sockfd, struct sockaddr *addr, socklen_t * paddrlen) +int getpeername(int sockfd, struct sockaddr *addr, socklen_t *paddrlen) { +# ifdef __NR_getpeername + return INLINE_SYSCALL(getpeername, 3, sockfd, addr, paddrlen); +# else unsigned long args[3]; args[0] = sockfd; args[1] = (unsigned long) addr; args[2] = (unsigned long) paddrlen; return __socketcall(SYS_GETPEERNAME, args); +# endif } #endif -#endif #ifdef L_getsockname -libc_hidden_proto(getsockname) -#ifdef __NR_getsockname -_syscall3(int, getsockname, int, sockfd, struct sockaddr *, addr, socklen_t *,paddrlen); -#elif defined(__NR_socketcall) int getsockname(int sockfd, struct sockaddr *addr, socklen_t * paddrlen) { +# ifdef __NR_getsockname + return INLINE_SYSCALL(getsockname, 3, sockfd, addr, paddrlen); +# else unsigned long args[3]; args[0] = sockfd; args[1] = (unsigned long) addr; args[2] = (unsigned long) paddrlen; return __socketcall(SYS_GETSOCKNAME, args); +# endif } -#endif libc_hidden_def(getsockname) #endif #ifdef L_getsockopt -#ifdef __NR_getsockopt -_syscall5(int, getsockopt, int, fd, int, level, int, optname, __ptr_t, optval, socklen_t *, optlen); -#elif defined(__NR_socketcall) -int getsockopt(int fd, int level, int optname, __ptr_t optval, - socklen_t * optlen) +int getsockopt(int fd, int level, int optname, void *optval, + socklen_t *optlen) { +# ifdef __NR_getsockopt + return INLINE_SYSCALL(getsockopt, 5, fd, level, optname, optval, optlen); +# else unsigned long args[5]; args[0] = fd; @@ -143,68 +197,56 @@ int getsockopt(int fd, int level, int optname, __ptr_t optval, args[3] = (unsigned long) optval; args[4] = (unsigned long) optlen; return (__socketcall(SYS_GETSOCKOPT, args)); +# endif } #endif -#endif #ifdef L_listen -libc_hidden_proto(listen) -#ifdef __NR_listen -_syscall2(int, listen, int, sockfd, int, backlog); -#elif defined(__NR_socketcall) int listen(int sockfd, int backlog) { +# ifdef __NR_listen + return INLINE_SYSCALL(listen, 2, sockfd, backlog); +# else unsigned long args[2]; args[0] = sockfd; args[1] = backlog; return __socketcall(SYS_LISTEN, args); +# endif } -#endif libc_hidden_def(listen) #endif #ifdef L_recv -extern __typeof(recv) __libc_recv; -#ifdef __NR_recv -#define __NR___libc_recv __NR_recv -_syscall4(ssize_t, __libc_recv, int, sockfd, __ptr_t, buffer, size_t, len, - int, flags); -#elif defined(__NR_socketcall) -/* recv, recvfrom added by bir7@leland.stanford.edu */ -ssize_t __libc_recv(int sockfd, __ptr_t buffer, size_t len, int flags) +static ssize_t __NC(recv)(int sockfd, void *buffer, size_t len, int flags) { +# ifdef __NR_recv + return (ssize_t)INLINE_SYSCALL(recv, 4, sockfd, buffer, len, flags); +# elif defined __NR_recvfrom && defined _syscall6 + return __NC(recvfrom)(sockfd, buffer, len, flags, NULL, NULL); +# else unsigned long args[4]; args[0] = sockfd; args[1] = (unsigned long) buffer; args[2] = len; args[3] = flags; - return (__socketcall(SYS_RECV, args)); -} -#elif defined(__NR_recvfrom) -libc_hidden_proto(recvfrom) -ssize_t __libc_recv(int sockfd, __ptr_t buffer, size_t len, int flags) -{ - return (recvfrom(sockfd, buffer, len, flags, NULL, NULL)); + return (ssize_t)__socketcall(SYS_RECV, args); +# endif } -#endif -libc_hidden_proto(recv) -weak_alias(__libc_recv,recv) -libc_hidden_weak(recv) +CANCELLABLE_SYSCALL(ssize_t, recv, (int sockfd, void *buffer, size_t len, int flags), + (sockfd, buffer, len, flags)) +lt_libc_hidden(recv) #endif #ifdef L_recvfrom -extern __typeof(recvfrom) __libc_recvfrom; -#ifdef __NR_recvfrom -#define __NR___libc_recvfrom __NR_recvfrom -_syscall6(ssize_t, __libc_recvfrom, int, sockfd, __ptr_t, buffer, size_t, len, - int, flags, struct sockaddr *, to, socklen_t *, tolen); -#elif defined(__NR_socketcall) -/* recv, recvfrom added by bir7@leland.stanford.edu */ -ssize_t __libc_recvfrom(int sockfd, __ptr_t buffer, size_t len, int flags, - struct sockaddr *to, socklen_t * tolen) +ssize_t __NC(recvfrom)(int sockfd, void *buffer, size_t len, int flags, + struct sockaddr *to, socklen_t *tolen) { +# if defined __NR_recvfrom && defined _syscall6 + return (ssize_t)INLINE_SYSCALL(recvfrom, 6, sockfd, buffer, len, + flags, to, tolen); +# else unsigned long args[6]; args[0] = sockfd; @@ -213,96 +255,82 @@ ssize_t __libc_recvfrom(int sockfd, __ptr_t buffer, size_t len, int flags, args[3] = flags; args[4] = (unsigned long) to; args[5] = (unsigned long) tolen; - return (__socketcall(SYS_RECVFROM, args)); + return (ssize_t)__socketcall(SYS_RECVFROM, args); +# endif } -#endif -libc_hidden_proto(recvfrom) -weak_alias(__libc_recvfrom,recvfrom) -libc_hidden_weak(recvfrom) +CANCELLABLE_SYSCALL(ssize_t, recvfrom, (int sockfd, void *buffer, size_t len, + int flags, struct sockaddr *to, socklen_t *tolen), + (sockfd, buffer, len, flags, to, tolen)) +lt_libc_hidden(recvfrom) #endif #ifdef L_recvmsg -extern __typeof(recvmsg) __libc_recvmsg; -#ifdef __NR_recvmsg -#define __NR___libc_recvmsg __NR_recvmsg -_syscall3(ssize_t, __libc_recvmsg, int, sockfd, struct msghdr *, msg, int, flags); -#elif defined(__NR_socketcall) -ssize_t __libc_recvmsg(int sockfd, struct msghdr *msg, int flags) +static ssize_t __NC(recvmsg)(int sockfd, struct msghdr *msg, int flags) { +# ifdef __NR_recvmsg + return (ssize_t)INLINE_SYSCALL(recvmsg, 3, sockfd, msg, flags); +# else unsigned long args[3]; args[0] = sockfd; args[1] = (unsigned long) msg; args[2] = flags; - return (__socketcall(SYS_RECVMSG, args)); + return (ssize_t)__socketcall(SYS_RECVMSG, args); +# endif } -#endif -libc_hidden_proto(recvmsg) -weak_alias(__libc_recvmsg,recvmsg) -libc_hidden_weak(recvmsg) +CANCELLABLE_SYSCALL(ssize_t, recvmsg, (int sockfd, struct msghdr *msg, int flags), + (sockfd, msg, flags)) +lt_libc_hidden(recvmsg) #endif #ifdef L_send -extern __typeof(send) __libc_send; -#ifdef __NR_send -#define __NR___libc_send __NR_send -_syscall4(ssize_t, __libc_send, int, sockfd, const void *, buffer, size_t, len, int, flags); -#elif defined(__NR_socketcall) -/* send, sendto added by bir7@leland.stanford.edu */ -ssize_t __libc_send(int sockfd, const void *buffer, size_t len, int flags) +static ssize_t __NC(send)(int sockfd, const void *buffer, size_t len, int flags) { +# ifdef __NR_send + return (ssize_t)INLINE_SYSCALL(send, 4, sockfd, buffer, len, flags); +# elif defined __NR_sendto && defined _syscall6 + return __NC(sendto)(sockfd, buffer, len, flags, NULL, 0); +# else unsigned long args[4]; args[0] = sockfd; args[1] = (unsigned long) buffer; args[2] = len; args[3] = flags; - return (__socketcall(SYS_SEND, args)); -} -#elif defined(__NR_sendto) -libc_hidden_proto(sendto) -ssize_t __libc_send(int sockfd, const void *buffer, size_t len, int flags) -{ - return (sendto(sockfd, buffer, len, flags, NULL, 0)); + return (ssize_t)__socketcall(SYS_SEND, args); +# endif } -#endif -libc_hidden_proto(send) -weak_alias(__libc_send,send) -libc_hidden_weak(send) +CANCELLABLE_SYSCALL(ssize_t, send, (int sockfd, const void *buffer, size_t len, int flags), + (sockfd, buffer, len, flags)) +lt_libc_hidden(send) #endif #ifdef L_sendmsg -extern __typeof(sendmsg) __libc_sendmsg; -#ifdef __NR_sendmsg -#define __NR___libc_sendmsg __NR_sendmsg -_syscall3(ssize_t, __libc_sendmsg, int, sockfd, const struct msghdr *, msg, int, flags); -#elif defined(__NR_socketcall) -ssize_t __libc_sendmsg(int sockfd, const struct msghdr *msg, int flags) +static ssize_t __NC(sendmsg)(int sockfd, const struct msghdr *msg, int flags) { +# ifdef __NR_sendmsg + return (ssize_t)INLINE_SYSCALL(sendmsg, 3, sockfd, msg, flags); +# else unsigned long args[3]; args[0] = sockfd; args[1] = (unsigned long) msg; args[2] = flags; - return (__socketcall(SYS_SENDMSG, args)); + return (ssize_t)__socketcall(SYS_SENDMSG, args); +# endif } -#endif -libc_hidden_proto(sendmsg) -weak_alias(__libc_sendmsg,sendmsg) -libc_hidden_weak(sendmsg) +CANCELLABLE_SYSCALL(ssize_t, sendmsg, (int sockfd, const struct msghdr *msg, int flags), + (sockfd, msg, flags)) +lt_libc_hidden(sendmsg) #endif #ifdef L_sendto -extern __typeof(sendto) __libc_sendto; -#ifdef __NR_sendto -#define __NR___libc_sendto __NR_sendto -_syscall6(ssize_t, __libc_sendto, int, sockfd, const void *, buffer, - size_t, len, int, flags, const struct sockaddr *, to, socklen_t, tolen); -#elif defined(__NR_socketcall) -/* send, sendto added by bir7@leland.stanford.edu */ -ssize_t __libc_sendto(int sockfd, const void *buffer, size_t len, int flags, - const struct sockaddr *to, socklen_t tolen) +ssize_t __NC(sendto)(int sockfd, const void *buffer, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen) { +# if defined __NR_sendto && defined _syscall6 + return (ssize_t)INLINE_SYSCALL(sendto, 6, sockfd, buffer, len, flags, to, tolen); +# else unsigned long args[6]; args[0] = sockfd; @@ -311,23 +339,21 @@ ssize_t __libc_sendto(int sockfd, const void *buffer, size_t len, int flags, args[3] = flags; args[4] = (unsigned long) to; args[5] = tolen; - return (__socketcall(SYS_SENDTO, args)); + return (ssize_t)__socketcall(SYS_SENDTO, args); +# endif } -#endif -libc_hidden_proto(sendto) -weak_alias(__libc_sendto,sendto) -libc_hidden_weak(sendto) +CANCELLABLE_SYSCALL(ssize_t, sendto, (int sockfd, const void *buffer, size_t len, + int flags, const struct sockaddr *to, socklen_t tolen), + (sockfd, buffer, len, flags, to, tolen)) +lt_libc_hidden(sendto) #endif #ifdef L_setsockopt -libc_hidden_proto(setsockopt) -#ifdef __NR_setsockopt -_syscall5(int, setsockopt, int, fd, int, level, int, optname, const void *, optval, socklen_t, optlen); -#elif defined(__NR_socketcall) -/* [sg]etsockoptions by bir7@leland.stanford.edu */ -int setsockopt(int fd, int level, int optname, const void *optval, - socklen_t optlen) +int setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) { +# ifdef __NR_setsockopt + return INLINE_SYSCALL(setsockopt, 5, fd, level, optname, optval, optlen); +# else unsigned long args[5]; args[0] = fd; @@ -335,52 +361,50 @@ int setsockopt(int fd, int level, int optname, const void *optval, args[2] = optname; args[3] = (unsigned long) optval; args[4] = optlen; - return (__socketcall(SYS_SETSOCKOPT, args)); + return __socketcall(SYS_SETSOCKOPT, args); +# endif } -#endif libc_hidden_def(setsockopt) #endif #ifdef L_shutdown -#ifdef __NR_shutdown -_syscall2(int, shutdown, int, sockfd, int, how); -#elif defined(__NR_socketcall) -/* shutdown by bir7@leland.stanford.edu */ int shutdown(int sockfd, int how) { +# ifdef __NR_shutdown + return INLINE_SYSCALL(shutdown, 2, sockfd, how); +# else unsigned long args[2]; args[0] = sockfd; args[1] = how; - return (__socketcall(SYS_SHUTDOWN, args)); + return __socketcall(SYS_SHUTDOWN, args); +# endif } #endif -#endif #ifdef L_socket -libc_hidden_proto(socket) -#ifdef __NR_socket -_syscall3(int, socket, int, family, int, type, int, protocol); -#elif defined(__NR_socketcall) int socket(int family, int type, int protocol) { +# ifdef __NR_socket + return INLINE_SYSCALL(socket, 3, family, type, protocol); +# else unsigned long args[3]; args[0] = family; args[1] = type; args[2] = (unsigned long) protocol; return __socketcall(SYS_SOCKET, args); +# endif } -#endif libc_hidden_def(socket) #endif #ifdef L_socketpair -#ifdef __NR_socketpair -_syscall4(int, socketpair, int, family, int, type, int, protocol, int *, sockvec); -#elif defined(__NR_socketcall) int socketpair(int family, int type, int protocol, int sockvec[2]) { +# ifdef __NR_socketpair + return INLINE_SYSCALL(socketpair, 4, family, type, protocol, sockvec); +# else unsigned long args[4]; args[0] = family; @@ -388,6 +412,6 @@ int socketpair(int family, int type, int protocol, int sockvec[2]) args[2] = protocol; args[3] = (unsigned long) sockvec; return __socketcall(SYS_SOCKETPAIR, args); +# endif } #endif -#endif |
