-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
replace problematic hostentdb with hostsreader
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
Showing
5 changed files
with
122 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |