-
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 hostent lookup with better performing in-memory copy.
the central dns resolver function proxy_gethostbyname() used to iterate over the gethostent() db (/etc/hosts) on each dns request. since this is not threadsafe, we synchronized access to it previously using mutexes. the parsing of this file is slow, and blocking all threads to do it even moreso. since gethostent_r() is only available on a few platforms, i decided to read the hostent db once and then use a quick in-memory lookup on further usage. + some further refactoring.
- Loading branch information
Showing
11 changed files
with
208 additions
and
39 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 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#include "hash.h" | ||
|
||
/* dalias' version of the elf hash */ | ||
uint32_t dalias_hash(char *s0) { | ||
unsigned char *s = (void *) s0; | ||
uint_fast32_t h = 0; | ||
while(*s) { | ||
h = 16 * h + *s++; | ||
h ^= h >> 24 & 0xf0; | ||
} | ||
return h & 0xfffffff; | ||
} |
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,10 @@ | ||
#ifndef HASH_H | ||
#define HASH_H | ||
|
||
#include <stdint.h> | ||
|
||
uint32_t dalias_hash(char *s0); | ||
|
||
//RcB: DEP "hash.c" | ||
|
||
#endif |
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,56 @@ | ||
#include <stdint.h> | ||
#include <string.h> | ||
#include <netdb.h> | ||
#include <stdlib.h> | ||
|
||
#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) { | ||
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])) }); | ||
} | ||
} | ||
|
||
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; | ||
} |
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,23 @@ | ||
#ifndef HOSTENTDB_H | ||
#define HOSTENTDB_H | ||
|
||
#include "ip_type.h" | ||
#include <unistd.h> | ||
|
||
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 |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#include "stringdump.h" | ||
#include "debug.h" | ||
|
||
struct stringpool mem; | ||
|
||
char *dumpstring(char* s, size_t len) { | ||
PFUNC(); | ||
return stringpool_add(&mem, s, len); | ||
} | ||
|
||
void dumpstring_init(void) { | ||
stringpool_init(&mem); | ||
} |
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,12 @@ | ||
#ifndef STRINGDUMP_H | ||
#define STRINGDUMP_H | ||
|
||
#include "shm.h" | ||
#include <unistd.h> | ||
|
||
char *dumpstring(char* s, size_t len); | ||
void dumpstring_init(void); | ||
|
||
//RcB: DEP "stringdump.h" | ||
|
||
#endif |
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,61 @@ | ||
#include <netdb.h> | ||
#include <stdio.h> | ||
#include <errno.h> | ||
#include "../src/common.h" | ||
|
||
/* | ||
int gethostent_r( | ||
struct hostent *ret, char *buf, size_t buflen, | ||
struct hostent **result, int *h_errnop); | ||
Glibc2 also has reentrant versions gethostent_r(), gethostbyaddr_r(), | ||
gethostbyname_r() and gethostbyname2_r(). | ||
The caller supplies a hostent structure ret which will be filled in on success, | ||
and a temporary work buffer buf of size buflen. | ||
After the call, result will point to the result on success. | ||
In case of an error or if no entry is found result will be NULL. | ||
The functions return 0 on success and a nonzero error number on failure. | ||
In addition to the errors returned by the nonreentrant versions of these functions, | ||
if buf is too small, the functions will return ERANGE, and the call should be retried | ||
with a larger buffer. | ||
The global variable h_errno is not modified, but the address of a variable in which | ||
to store error numbers is passed in h_errnop. | ||
*/ | ||
|
||
void printhostent(struct hostent *hp) { | ||
char ipbuf[16]; | ||
pc_stringfromipv4(hp->h_addr_list[0], ipbuf); | ||
printf("alias: %p, len: %d, name: %s, addrlist: %p, addrtype: %d, ip: %s\n", | ||
hp->h_aliases, | ||
hp->h_length, | ||
hp->h_name, | ||
hp->h_addr_list, | ||
hp->h_addrtype, | ||
ipbuf | ||
); | ||
} | ||
|
||
int main(int argc, char** argv) { | ||
struct hostent he_buf; | ||
struct hostent *he_res; | ||
char h_buf[1024]; | ||
int ch_errno; | ||
int ret; | ||
do { | ||
ret = gethostent_r(&he_buf, h_buf, sizeof(h_buf), &he_res, &ch_errno); | ||
printf("ret: %d, h_errno: %d\n", ret, ch_errno); | ||
if(ret != 0) { | ||
errno = ret; | ||
ret = -1; | ||
} | ||
if(ret == -1) { | ||
perror("gethostent_r"); | ||
break; | ||
} | ||
if(he_res) { | ||
printhostent(he_res); | ||
} | ||
} while (he_res); | ||
return 0; | ||
} |