summaryrefslogtreecommitdiff
path: root/libc/inet/resolv.c
diff options
context:
space:
mode:
authorBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2010-03-01 14:40:45 +0100
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2010-08-05 23:42:41 +0200
commitf65e66078b9f4d2d7f0fc336dee36e78fc467c0f (patch)
treee99682f1d15f036812ffa58840987f10114e84c9 /libc/inet/resolv.c
parent14c25c92be68a13d3ac94bdc46b16ba2590de4c9 (diff)
resolver: switch to config parser
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Diffstat (limited to 'libc/inet/resolv.c')
-rw-r--r--libc/inet/resolv.c255
1 files changed, 119 insertions, 136 deletions
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
index 6a9b80791..d45e5f8a0 100644
--- a/libc/inet/resolv.c
+++ b/libc/inet/resolv.c
@@ -124,6 +124,9 @@
*
* 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:
@@ -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,
@@ -1571,19 +1576,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,
@@ -1592,112 +1597,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;
}
@@ -1709,7 +1692,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;
@@ -1718,7 +1701,7 @@ int attribute_hidden __read_etc_hosts_r(
break;
}
if (action != GETHOSTENT)
- fclose(fp);
+ config_close(parser);
return ret;
#undef in6
}
@@ -1795,7 +1778,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))
@@ -1832,31 +1815,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
@@ -2424,8 +2407,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;
@@ -2524,24 +2505,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);
}
@@ -2551,21 +2537,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;
@@ -2578,18 +2562,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
@@ -2602,13 +2585,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
}
@@ -2621,13 +2604,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);
@@ -2642,17 +2625,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)
@@ -3052,7 +3035,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__