|
@@ -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
|
|
|
*/
|
|
|
|
|
|
* 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"
|
|
|
|
|
|
|
|
|
* 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
|
|
|
|
|
|
-
|
|
|
-#define ALIAS_DIM (2 + MAX_ALIASES + 1)
|
|
|
+#define MAX_RECURSE 5
|
|
|
+#define MAXALIASES (6)
|
|
|
+#define BUFSZ (80)
|
|
|
+#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXALIASES))
|
|
|
|
|
|
#undef DEBUG
|
|
|
|
|
@@ -422,7 +426,8 @@ extern const struct sockaddr_in6 __local_nameserver attribute_hidden;
|
|
|
#define MAXLEN_searchdomain 128
|
|
|
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+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;
|
|
|
-
|
|
|
-
|
|
|
- i = ALIGN_BUFFER_OFFSET(buf);
|
|
|
- buf += i;
|
|
|
- buflen -= i;
|
|
|
-
|
|
|
- * 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;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ * 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))
|
|
|
+
|
|
|
+ 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;
|
|
|
-
|
|
|
+ *alias = NULL;
|
|
|
if (action == GETHOSTENT) {
|
|
|
|
|
|
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 {
|
|
|
-
|
|
|
- for (i = 1; i < aliases; i++)
|
|
|
- if (strcasecmp(name, alias[i]) == 0)
|
|
|
+ } else {
|
|
|
+ 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) ;
|
|
|
#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");
|
|
|
|
|
|
* 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) ;
|
|
|
#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
|
|
|
- sizeof(char *) * ALIAS_DIM +
|
|
|
- 80 + 2 ];
|
|
|
+ BUFSZ + 2 ];
|
|
|
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 + 32];
|
|
|
+ 384 + 32];
|
|
|
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 + 32];
|
|
|
+ 384 + 32];
|
|
|
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
|
|
|
- sizeof(char *)*ALIAS_DIM + 384 + 32 ];
|
|
|
+ 384 + 32 ];
|
|
|
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
|
|
|
+#else
|
|
|
struct __res_state _res __attribute__((section (".bss"))) attribute_hidden;
|
|
|
|
|
|
# if defined __UCLIBC_HAS_TLS__
|