[PATCH 7/7] resolver: switch to config parser

Bernhard Reutner-Fischer rep.dot.nop at gmail.com
Fri Apr 16 09:35:55 UTC 2010


Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop at gmail.com>
---
 libc/inet/resolv.c |  255 ++++++++++++++++++++++++----------------------------
 1 files changed, 119 insertions(+), 136 deletions(-)

diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
index 84289a6..92eefef 100644
--- a/libc/inet/resolv.c
+++ b/libc/inet/resolv.c
@@ -124,6 +124,9 @@
  *
  * 2008, 2009 Denys Vlasenko <vda.linux at 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:
@@ -314,6 +317,7 @@ Domain name in a message can be represented as either:
 #include <sys/un.h>
 #include <sys/stat.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
@@ -329,11 +333,11 @@ Domain name in a message can be represented as either:
 #define IF_HAS_BOTH(...)
 #endif
 
-#define MAX_RECURSE    5
-#define MAX_ALIASES    5
 
-/* 1:ip + 1:full + MAX_ALIASES:aliases + 1:NULL */
-#define ALIAS_DIM      (2 + MAX_ALIASES + 1)
+#define MAX_RECURSE    5
+#define MAXALIASES  (6)
+#define BUFSZ       (80) /* one line */
+#define SBUFSIZE    (BUFSZ + 1 + (sizeof(char *) * MAXALIASES))
 
 #undef DEBUG
 /* #define DEBUG */
@@ -422,7 +426,8 @@ extern const struct sockaddr_in6 __local_nameserver attribute_hidden;
 #define MAXLEN_searchdomain 128
 
 
-/* function prototypes */
+/* 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,
@@ -438,8 +443,8 @@ extern int __get_hosts_byaddr_r(const char *addr,
 		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,
+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,
@@ -1569,19 +1574,19 @@ int attribute_hidden __dns_lookup(const char *name,
 
 #ifdef L_read_etc_hosts_r
 
-FILE * __open_etc_hosts(void)
+parser_t * __open_etc_hosts(void)
 {
-	FILE * fp;
-	if ((fp = fopen("/etc/hosts", "r")) == NULL) {
+	parser_t * parser;
+	if ((parser = config_open("/etc/hosts")) == NULL) {
 #ifdef FALLBACK_TO_CONFIG_RESOLVCONF
-		fp = fopen("/etc/config/hosts", "r");
+		parser = config_open("/etc/config/hosts");
 #endif
 	}
-	return fp;
+	return parser;
 }
 
 int attribute_hidden __read_etc_hosts_r(
-		FILE * fp,
+		parser_t * parser,
 		const char *name,
 		int type,
 		enum etc_hosts_action action,
@@ -1590,112 +1595,90 @@ int attribute_hidden __read_etc_hosts_r(
 		struct hostent **result,
 		int *h_errnop)
 {
-	struct in_addr **addr_list = NULL;
-	struct in_addr *in = NULL;
-	char *cp, **alias;
-	int aliases, i, ret = HOST_NOT_FOUND;
-
-	*h_errnop = NETDB_INTERNAL;
-
-	/* 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 line_buffer[80+];
-	 */
-#define in6 ((struct in6_addr *)in)
-	alias = (char **)buf;
-	buf += sizeof(char **) * ALIAS_DIM;
-	buflen -= sizeof(char **) * ALIAS_DIM;
-	if ((ssize_t)buflen < 0)
-		return ERANGE;
-	if (action != GETHOSTENT) {
-		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);
+	char **alias, *cp = NULL;
+	char **host_aliases;
+	char **tok = NULL;
+	struct in_addr *h_addr0 = NULL;
+#define ALIASOFF (sizeof(*host_aliases) * MAXALIASES + 2 * sizeof(char*))
+	const size_t aliaslen = ALIASOFF +
+#ifdef __UCLIBC_HAS_IPV6__
+							sizeof(struct in6_addr)
 #else
-		buf += sizeof(*in6);
-		buflen -= sizeof(*in6);
+							sizeof(struct in_addr)
 #endif
-		if ((ssize_t)buflen < 80)
-			return ERANGE;
+							;
+	int ret = HOST_NOT_FOUND;
 
-		fp = __open_etc_hosts();
-		if (fp == NULL) {
-			*result = NULL;
-			return errno;
-		}
-		addr_list[0] = in;
-		addr_list[1] = NULL;
+	*h_errnop = NETDB_INTERNAL;
+	if (buflen < aliaslen
+		|| (buflen - aliaslen) < BUFSZ + 1)
+		return ERANGE;
+	if (parser == NULL)
+		parser = __open_etc_hosts();
+	if (parser == NULL) {
+		*result = NULL;
+		return errno;
 	}
-
+	/* Layout in buf:
+	 * char **alias for MAXALIAS 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)) {
-		*strchrnul(buf, '#') = '\0';
-		DPRINTF("Looking at: %s\n", buf);
-		aliases = 0;
-
-		cp = buf;
-		while (*cp) {
-			while (*cp && isspace(*cp))
+	/* <ip>[[:space:]][<aliases>] */
+	while (config_read(parser, &tok, 2, 2, "# \t", PARSE_NORMAL)) {
+		result_buf->h_aliases = alias = host_aliases = tok+1;
+		cp = *alias;
+		while (cp && *cp) {
+			if (alias < &host_aliases[MAXALIASES - 1])
+				*alias++ = cp;
+			cp = strpbrk(cp, " \t");
+			if (cp != NULL)
 				*cp++ = '\0';
-			if (!*cp)
-				break;
-			if (aliases < (2 + MAX_ALIASES))
-				alias[aliases++] = cp;
-			while (*cp && !isspace(*cp))
-				cp++;
 		}
-		alias[aliases] = NULL;
-
-		if (aliases < 2)
-			continue; /* syntax error really */
-
+		*alias = NULL;
 		if (action == GETHOSTENT) {
 			/* Return whatever the next entry happens to be. */
 			break;
 		}
+		result_buf->h_name = *(result_buf->h_aliases++);
 		if (action == GET_HOSTS_BYADDR) {
-			if (strcmp(name, alias[0]) != 0)
+			if (strcmp(name, result_buf->h_name) != 0)
 				continue;
-		} else {
-			/* GET_HOSTS_BYNAME */
-			for (i = 1; i < aliases; i++)
-				if (strcasecmp(name, alias[i]) == 0)
+		} else { /* GET_HOSTS_BYNAME */
+			alias = result_buf->h_aliases;
+			while ((cp = *(alias++)))
+				if (strcasecmp(name, cp) == 0)
 					goto found;
 			continue;
- found: ;
 		}
-
+found:
+		result_buf->h_addr_list = (char**)(buf + ALIASOFF);
+		*(result_buf->h_addr_list + 1) = '\0';
+		h_addr0 = (struct in_addr*)(buf + ALIASOFF + 2 * sizeof (char*));
+		result_buf->h_addr = (char*)h_addr0;
 		if (0) /* nothing */;
 #ifdef __UCLIBC_HAS_IPV4__
-		else if (type == AF_INET && inet_pton(AF_INET, alias[0], in) > 0) {
+		else if (type == AF_INET
+				&& inet_pton(AF_INET, *tok, h_addr0) > 0) {
 			DPRINTF("Found INET\n");
 			result_buf->h_addrtype = AF_INET;
-			result_buf->h_length = sizeof(*in);
-			result_buf->h_name = alias[1];
-			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");
 			result_buf->h_addrtype = AF_INET6;
-			result_buf->h_length = sizeof(*in6);
-			result_buf->h_name = alias[1];
-			result_buf->h_addr_list = (char**) addr_list;
-			result_buf->h_aliases = alias + 2;
+			result_buf->h_length = sizeof(struct in6_addr);
 			*result = result_buf;
 			ret = NETDB_SUCCESS;
 		}
@@ -1707,7 +1690,7 @@ int attribute_hidden __read_etc_hosts_r(
 			 * <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;
@@ -1716,7 +1699,7 @@ int attribute_hidden __read_etc_hosts_r(
 		break;
 	}
 	if (action != GETHOSTENT)
-		fclose(fp);
+		config_close(parser);
 	return ret;
 #undef in6
 }
@@ -1793,7 +1776,7 @@ int getnameinfo(const struct sockaddr *sa,
 {
 	int serrno = errno;
 	unsigned ok;
-	struct hostent *h = NULL;
+	struct hostent *hoste = NULL;
 	char domain[256];
 
 	if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM))
@@ -1830,31 +1813,31 @@ int getnameinfo(const struct sockaddr *sa,
 				if (0) /* nothing */;
 #ifdef __UCLIBC_HAS_IPV6__
 				else if (sa->sa_family == AF_INET6)
-					h = gethostbyaddr((const void *)
+					hoste = gethostbyaddr((const void *)
 						&(((const struct sockaddr_in6 *) sa)->sin6_addr),
 						sizeof(struct in6_addr), AF_INET6);
 #endif
 #ifdef __UCLIBC_HAS_IPV4__
 				else
-					h = gethostbyaddr((const void *)
+					hoste = gethostbyaddr((const void *)
 						&(((const struct sockaddr_in *)sa)->sin_addr),
 						sizeof(struct in_addr), AF_INET);
 #endif
 
-				if (h) {
+				if (hoste) {
 					char *c;
 #undef min
 #define min(x,y) (((x) > (y)) ? (y) : (x))
 					if ((flags & NI_NOFQDN)
 					 && (getdomainname(domain, sizeof(domain)) == 0)
-					 && (c = strstr(h->h_name, domain)) != NULL
-					 && (c != h->h_name) && (*(--c) == '.')
+					 && (c = strstr(hoste->h_name, domain)) != NULL
+					 && (c != hoste->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';
+						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);
+						strncpy(host, hoste->h_name, hostlen);
 					}
 					ok = 1;
 #undef min
@@ -2422,8 +2405,6 @@ int gethostbyaddr_r(const void *addr, socklen_t addrlen,
 	 */
 #define in6 ((struct in6_addr *)in)
 	alias = (char **)buf;
-	buf += sizeof(*alias) * ALIAS_DIM;
-	buflen -= sizeof(*alias) * ALIAS_DIM;
 	addr_list = (struct in_addr**)buf;
 	buf += sizeof(*addr_list) * 2;
 	buflen -= sizeof(*addr_list) * 2;
@@ -2518,24 +2499,29 @@ link_warning(gethostbyaddr_r, "gethostbyaddr_r is obsolescent, use getaddrinfo()
 
 __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
 
-static smallint __stay_open;
-static FILE * __gethostent_fp;
+static parser_t *hostp = NULL;
+static smallint host_stayopen;
 
+void endhostent_unlocked(void)
+{
+	if (hostp) {
+		config_close(hostp);
+		hostp = NULL;
+	}
+	host_stayopen = 0;
+}
 void endhostent(void)
 {
 	__UCLIBC_MUTEX_LOCK(mylock);
-	__stay_open = 0;
-	if (__gethostent_fp) {
-		fclose(__gethostent_fp);
-		__gethostent_fp = NULL;
-	}
+	endhostent_unlocked();
 	__UCLIBC_MUTEX_UNLOCK(mylock);
 }
 
 void sethostent(int stay_open)
 {
 	__UCLIBC_MUTEX_LOCK(mylock);
-	__stay_open = (stay_open != 0);
+	if (stay_open)
+		host_stayopen = 1;
 	__UCLIBC_MUTEX_UNLOCK(mylock);
 }
 
@@ -2545,21 +2531,19 @@ int gethostent_r(struct hostent *result_buf, char *buf, size_t buflen,
 	int ret;
 
 	__UCLIBC_MUTEX_LOCK(mylock);
-	if (__gethostent_fp == NULL) {
-		__gethostent_fp = __open_etc_hosts();
-		if (__gethostent_fp == NULL) {
+	if (hostp == NULL) {
+		hostp = __open_etc_hosts();
+		if (hostp == NULL) {
 			*result = NULL;
 			ret = TRY_AGAIN;
 			goto DONE;
 		}
 	}
 
-	ret = __read_etc_hosts_r(__gethostent_fp, NULL, AF_INET, GETHOSTENT,
+	ret = __read_etc_hosts_r(hostp, NULL, AF_INET, GETHOSTENT,
 		   result_buf, buf, buflen, result, h_errnop);
-	if (__stay_open == 0) {
-		fclose(__gethostent_fp);
-		__gethostent_fp = NULL;
-	}
+	if (!host_stayopen)
+		endhostent_unlocked();
 DONE:
 	__UCLIBC_MUTEX_UNLOCK(mylock);
 	return ret;
@@ -2572,18 +2556,17 @@ libc_hidden_def(gethostent_r)
 
 struct hostent *gethostent(void)
 {
-	static struct hostent h;
+	static struct hostent hoste;
 	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 */];
+			BUFSZ /*namebuffer*/ + 2 /* margin */];
 	struct hostent *host;
 
-	gethostent_r(&h, buf, sizeof(buf), &host, &h_errno);
+	gethostent_r(&hoste, buf, sizeof(buf), &host, &h_errno);
 	return host;
 }
 #endif
@@ -2596,13 +2579,13 @@ struct hostent *gethostbyname2(const char *name, int family)
 #ifndef __UCLIBC_HAS_IPV6__
 	return family == AF_INET ? gethostbyname(name) : (struct hostent*)NULL;
 #else
-	static struct hostent h;
+	static struct hostent hoste;
 	static char buf[sizeof(struct in6_addr) +
 			sizeof(struct in6_addr *) * 2 +
-			sizeof(char *)*ALIAS_DIM + 384/*namebuffer*/ + 32/* margin */];
+			/*sizeof(char *)*ALIAS_DIM +*/ 384/*namebuffer*/ + 32/* margin */];
 	struct hostent *hp;
 
-	gethostbyname2_r(name, family, &h, buf, sizeof(buf), &hp, &h_errno);
+	gethostbyname2_r(name, family, &hoste, buf, sizeof(buf), &hp, &h_errno);
 	return hp;
 #endif
 }
@@ -2615,13 +2598,13 @@ libc_hidden_def(gethostbyname2)
 struct hostent *gethostbyname(const char *name)
 {
 #ifndef __UCLIBC_HAS_IPV6__
-	static struct hostent h;
+	static struct hostent hoste;
 	static char buf[sizeof(struct in_addr) +
 			sizeof(struct in_addr *) * 2 +
-			sizeof(char *)*ALIAS_DIM + 384/*namebuffer*/ + 32/* margin */];
+			/*sizeof(char *)*ALIAS_DIM +*/ 384/*namebuffer*/ + 32/* margin */];
 	struct hostent *hp;
 
-	gethostbyname_r(name, &h, buf, sizeof(buf), &hp, &h_errno);
+	gethostbyname_r(name, &hoste, buf, sizeof(buf), &hp, &h_errno);
 	return hp;
 #else
 	return gethostbyname2(name, AF_INET);
@@ -2636,17 +2619,17 @@ link_warning(gethostbyname, "gethostbyname is obsolescent, use getnameinfo() ins
 
 struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type)
 {
-	static struct hostent h;
+	static struct hostent hoste;
 	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 + 384 /*namebuffer*/ + 32 /* margin */];
+			/*sizeof(char *)*ALIAS_DIM +*/ 384 /*namebuffer*/ + 32 /* margin */];
 	struct hostent *hp;
 
-	gethostbyaddr_r(addr, len, type, &h, buf, sizeof(buf), &hp, &h_errno);
+	gethostbyaddr_r(addr, len, type, &hoste, buf, sizeof(buf), &hp, &h_errno);
 	return hp;
 }
 libc_hidden_def(gethostbyaddr)
@@ -3046,7 +3029,7 @@ void res_close(void)
    which can have an alias.  */
 struct __res_state _res __attribute__((section (".bss")));
 struct __res_state *__resp = &_res;
-#else //__UCLIBC_HAS_THREADS__
+#else /* __UCLIBC_HAS_THREADS__ */
 struct __res_state _res __attribute__((section (".bss"))) attribute_hidden;
 
 # if defined __UCLIBC_HAS_TLS__
-- 
1.7.0



More information about the uClibc mailing list