diff --git a/Makefile b/Makefile index 3a179ea..0ebfa17 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ OBJS = $(SRCS:.c=.o) LOBJS = src/nameinfo.o src/version.o \ src/core.o src/common.o src/libproxychains.o src/shm.o \ src/allocator_thread.o src/ip_type.o src/stringdump.o \ - src/hostentdb.o src/hash.o src/debug.o + src/hostsreader.o src/hash.o src/debug.o GENH = src/version.h diff --git a/src/core.c b/src/core.c index 51a5973..49caf64 100644 --- a/src/core.c +++ b/src/core.c @@ -719,11 +719,7 @@ int connect_proxy_chain(int sock, ip_type target_ip, return -1; } -#include "hostentdb.h" -struct hostent_list hl; - void core_initialize(void) { - hdb_init(&hl); } void core_unload(void) { @@ -734,6 +730,7 @@ static void gethostbyname_data_setstring(struct gethostbyname_data* data, char* data->hostent_space.h_name = data->addr_name; } +extern ip_type hostsreader_get_numeric_ip_for_name(const char* name); struct hostent *proxy_gethostbyname(const char *name, struct gethostbyname_data* data) { PFUNC(); char buff[256]; @@ -758,10 +755,8 @@ struct hostent *proxy_gethostbyname(const char *name, struct gethostbyname_data* goto retname; } - memset(buff, 0, sizeof(buff)); - // this iterates over the "known hosts" db, usually /etc/hosts - ip_type hdb_res = hdb_get(&hl, (char*) name); + ip_type hdb_res = hostsreader_get_numeric_ip_for_name(name); if(hdb_res.as_int != ip_type_invalid.as_int) { data->resolved_addr = hdb_res.as_int; goto retname; diff --git a/src/hostentdb.c b/src/hostentdb.c deleted file mode 100644 index 488e983..000000000 --- a/src/hostentdb.c +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "ip_type.h" -#include "hash.h" -#include "stringdump.h" -#include "hostentdb.h" -#include "common.h" -#include "debug.h" - -#define STEP 16 -static void hdb_add(struct hostent_list* hl, char* host, ip_type ip) { - if(hl->count +1 > hl->capa) { - void * nu = realloc(hl->entries, (hl->capa + STEP) * sizeof(struct hostent_entry)); - if(!nu) return; - hl->entries = nu; - hl->capa += STEP; - } - struct hostent_entry *h = &hl->entries[hl->count]; - h->hash = dalias_hash(host); - h->ip.as_int = ip.as_int; - h->str = dumpstring(host, strlen(host) + 1); - if(h->str) hl->count++; -} - -static void hdb_fill(struct hostent_list *hl) { -#ifndef IS_BSD - struct hostent* hp; - while((hp = gethostent())) - if(hp->h_addrtype == AF_INET && hp->h_length == sizeof(in_addr_t)) { - hdb_add(hl, hp->h_name, (ip_type) { .as_int = *((in_addr_t*)(hp->h_addr_list[0])) }); - } -#else - /* FreeBSD hangs on gethostent(). since this feature is not crucial, we just do nothing */ - (void) hl; -#endif -} - -void hdb_init(struct hostent_list *hl) { - memset(hl, 0, sizeof *hl); - hdb_fill(hl); -} - -ip_type hdb_get(struct hostent_list *hl, char* host) { - size_t i; - PFUNC(); - uint32_t hash = dalias_hash(host); - for(i = 0; i < hl->count; i++) { - if(hl->entries[i].hash == hash && !strcmp(hl->entries[i].str, host)) { - #ifdef DEBUG - char ipbuf[16]; - pc_stringfromipv4(hl->entries[i].ip.octet, ipbuf); - PDEBUG("got ip %s for hostent entry %s\n", ipbuf, host); - #endif - return hl->entries[i].ip; - } - } - return ip_type_invalid; -} diff --git a/src/hostentdb.h b/src/hostentdb.h deleted file mode 100644 index 4f807d1..000000000 --- a/src/hostentdb.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef HOSTENTDB_H -#define HOSTENTDB_H - -#include "ip_type.h" -#include - -struct hostent_entry { - uint32_t hash; - ip_type ip; - char* str; -}; - -struct hostent_list { - size_t count; - size_t capa; - struct hostent_entry *entries; -}; - -void hdb_init(struct hostent_list *hl); -ip_type hdb_get(struct hostent_list *hl, char* host); - -//RcB: DEP "hostendb.c" -#endif diff --git a/src/hostsreader.c b/src/hostsreader.c new file mode 100644 index 000000000..d20a1a5 --- /dev/null +++ b/src/hostsreader.c @@ -0,0 +1,119 @@ +#include +#include +#include + +/* + simple reader for /etc/hosts + it only supports comments, blank lines and lines consisting of an ipv4 hostname pair. + this is required so we can return entries from the host db without messing up the + non-thread-safe state of libc's gethostent(). + +*/ + +struct hostsreader { + FILE *f; + char* ip, *name; +}; + +int hostsreader_open(struct hostsreader *ctx) { + if(!(ctx->f = fopen("/etc/hosts", "r"))) return 0; + return 1; +} + +void hostsreader_close(struct hostsreader *ctx) { + fclose(ctx->f); +} + +static int isnumericipv4(const char* ipstring); +int hostsreader_get(struct hostsreader *ctx, char* buf, size_t bufsize) { + while(1) { + if(!fgets(buf, bufsize, ctx->f)) return 0; + if(*buf == '#') continue; + ctx->ip = buf; + while(*buf && !isspace(*buf) && bufsize) { + buf++; + bufsize--; + } + if(!bufsize || !*buf || buf == ctx->ip) continue; + *buf = 0; + buf++; + while(*buf && isspace(*buf) && bufsize) { + buf++; + bufsize--; + } + if(!bufsize || !*buf) continue; + ctx->name = buf; + while(*buf && !isspace(*buf) && bufsize) { + buf++; + bufsize--; + } + if(!bufsize || !*buf) continue; + *buf = 0; + if(isnumericipv4(ctx->ip)) return 1; + } +} + +char* hostsreader_get_ip_for_name(const char* name, char* buf, size_t bufsize) { + struct hostsreader ctx; + char *res = 0; + if(!hostsreader_open(&ctx)) return 0; + while(hostsreader_get(&ctx, buf, bufsize)) { + if(!strcmp(ctx.name, name)) { + res = ctx.ip; + break; + } + } + hostsreader_close(&ctx); + return res; +} + +#include "ip_type.h" +#include +#include +#include +ip_type hostsreader_get_numeric_ip_for_name(const char* name) { + char *hres; + char buf[320]; + if((hres = hostsreader_get_ip_for_name(name, buf, sizeof buf))) { + struct in_addr c; + inet_aton(hres, &c); + ip_type res; + memcpy(res.octet, &c.s_addr, 4); + return res; + } else return ip_type_invalid; +} + +#ifdef HOSTSREADER_TEST +int main() { + char buf[256]; + char * ret = hostsreader_get_ip_for_name("goo", buf, sizeof buf); + printf("%s\n", ret ? ret : "null"); +} +#endif + +/* isnumericipv4() taken from libulz */ +static int isnumericipv4(const char* ipstring) { + size_t x = 0, n = 0, d = 0; + int wasdot = 0; + while(1) { + switch(ipstring[x]) { + case 0: goto done; + case '.': + if(!n || wasdot) return 0; + d++; + wasdot = 1; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + n++; + wasdot = 0; + break; + default: + return 0; + } + x++; + } + done: + if(d == 3 && n >= 4 && n <= 12) return 1; + return 0; +}