Skip to content

Commit

Permalink
replace problematic hostentdb with hostsreader
Browse files Browse the repository at this point in the history
the hostentdb introduced between 4.2 and 4.3
(via af5c6f0 )
had several issues:
- it caused breakage on FreeBSD and was commented out there
- prevented usage of the hostdb when proxy_dns was turned off
  (issue #42)
- required dynamic memory allocation which was accessed from several
  threads
- wouldnt reflect changes to the hosts file made during program run

the only sensible solution is to remove the hostentdb and replace it
with a home-grown hosts parser (we can't use gethostent() since
that would mess up the gethostent()-state from different threads).

the new parser used here is deliberately held simple and only meant
to provide the user with means to reference hardcoded ipv4 addresses
via his hosts file.

fixes #42
  • Loading branch information
rofl0r committed Nov 14, 2014
1 parent 567935b commit 4fb7eb0
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 94 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
9 changes: 2 additions & 7 deletions src/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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];
Expand All @@ -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;
Expand Down
63 changes: 0 additions & 63 deletions src/hostentdb.c

This file was deleted.

23 changes: 0 additions & 23 deletions src/hostentdb.h

This file was deleted.

119 changes: 119 additions & 0 deletions src/hostsreader.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>

/*
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 <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
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;
}

0 comments on commit 4fb7eb0

Please sign in to comment.