Merge "Add support for a dns cache per interface"
This commit is contained in:
commit
cc32fbc305
3 changed files with 480 additions and 21 deletions
|
@ -34,6 +34,7 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <arpa/nameser.h>
|
#include <arpa/nameser.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
@ -49,6 +50,21 @@ extern struct __res_state *__res_state(void);
|
||||||
extern int b64_ntop(u_char const *, size_t, char *, size_t);
|
extern int b64_ntop(u_char const *, size_t, char *, size_t);
|
||||||
extern int b64_pton(char const *, u_char *, size_t);
|
extern int b64_pton(char const *, u_char *, size_t);
|
||||||
|
|
||||||
|
/* Set name of default interface */
|
||||||
|
extern void _resolv_set_default_iface(const char* ifname);
|
||||||
|
|
||||||
|
/* set name servers for an interface */
|
||||||
|
extern void _resolv_set_nameservers_for_iface(const char* ifname, char** servers, int numservers);
|
||||||
|
|
||||||
|
/* tell resolver of the address of an interface */
|
||||||
|
extern void _resolv_set_addr_of_iface(const char* ifname, struct in_addr* addr);
|
||||||
|
|
||||||
|
/* flush the cache associated with the default interface */
|
||||||
|
extern void _resolv_flush_cache_for_default_iface();
|
||||||
|
|
||||||
|
/* flush the cache associated with a certain interface */
|
||||||
|
extern void _resolv_flush_cache_for_iface(const char* ifname);
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
#endif /* _RESOLV_H_ */
|
#endif /* _RESOLV_H_ */
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "resolv_cache.h"
|
#include "resolv_cache.h"
|
||||||
|
#include <resolv.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -35,6 +36,12 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "arpa_nameser.h"
|
#include "arpa_nameser.h"
|
||||||
#include <sys/system_properties.h>
|
#include <sys/system_properties.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include "resolv_private.h"
|
||||||
|
|
||||||
/* This code implements a small and *simple* DNS resolver cache.
|
/* This code implements a small and *simple* DNS resolver cache.
|
||||||
*
|
*
|
||||||
|
@ -159,9 +166,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include "resolv_private.h"
|
|
||||||
|
|
||||||
/** BOUNDED BUFFER FORMATTING
|
/** BOUNDED BUFFER FORMATTING
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
@ -1165,6 +1169,14 @@ typedef struct resolv_cache {
|
||||||
Entry* entries;
|
Entry* entries;
|
||||||
} Cache;
|
} Cache;
|
||||||
|
|
||||||
|
typedef struct resolv_cache_info {
|
||||||
|
char ifname[IF_NAMESIZE + 1];
|
||||||
|
struct in_addr ifaddr;
|
||||||
|
Cache* cache;
|
||||||
|
struct resolv_cache_info* next;
|
||||||
|
char* nameservers[MAXNS +1];
|
||||||
|
struct addrinfo* nsaddrinfo[MAXNS + 1];
|
||||||
|
} CacheInfo;
|
||||||
|
|
||||||
#define HTABLE_VALID(x) ((x) != NULL && (x) != HTABLE_DELETED)
|
#define HTABLE_VALID(x) ((x) != NULL && (x) != HTABLE_DELETED)
|
||||||
|
|
||||||
|
@ -1543,11 +1555,47 @@ Exit:
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
static struct resolv_cache* _res_cache;
|
|
||||||
static pthread_once_t _res_cache_once;
|
static pthread_once_t _res_cache_once;
|
||||||
|
|
||||||
|
// Head of the list of caches. Protected by _res_cache_list_lock.
|
||||||
|
static struct resolv_cache_info _res_cache_list;
|
||||||
|
|
||||||
|
// name of the current default inteface
|
||||||
|
static char _res_default_ifname[IF_NAMESIZE + 1];
|
||||||
|
|
||||||
|
// lock protecting everything in the _resolve_cache_info structs (next ptr, etc)
|
||||||
|
static pthread_mutex_t _res_cache_list_lock;
|
||||||
|
|
||||||
|
|
||||||
|
/* lookup the default interface name */
|
||||||
|
static char *_get_default_iface_locked();
|
||||||
|
/* insert resolv_cache_info into the list of resolv_cache_infos */
|
||||||
|
static void _insert_cache_info_locked(struct resolv_cache_info* cache_info);
|
||||||
|
/* creates a resolv_cache_info */
|
||||||
|
static struct resolv_cache_info* _create_cache_info( void );
|
||||||
|
/* gets cache associated with an interface name, or NULL if none exists */
|
||||||
|
static struct resolv_cache* _find_named_cache_locked(const char* ifname);
|
||||||
|
/* gets a resolv_cache_info associated with an interface name, or NULL if not found */
|
||||||
|
static struct resolv_cache_info* _find_cache_info_locked(const char* ifname);
|
||||||
|
/* free dns name server list of a resolv_cache_info structure */
|
||||||
|
static void _free_nameservers(struct resolv_cache_info* cache_info);
|
||||||
|
/* look up the named cache, and creates one if needed */
|
||||||
|
static struct resolv_cache* _get_res_cache_for_iface_locked(const char* ifname);
|
||||||
|
/* empty the named cache */
|
||||||
|
static void _flush_cache_for_iface_locked(const char* ifname);
|
||||||
|
/* empty the nameservers set for the named cache */
|
||||||
|
static void _free_nameservers_locked(struct resolv_cache_info* cache_info);
|
||||||
|
/* lookup the namserver for the name interface */
|
||||||
|
static int _get_nameserver_locked(const char* ifname, int n, char* addr, int addrLen);
|
||||||
|
/* lookup the addr of the nameserver for the named interface */
|
||||||
|
static struct addrinfo* _get_nameserver_addr_locked(const char* ifname, int n);
|
||||||
|
/* lookup the inteface's address */
|
||||||
|
static struct in_addr* _get_addr_locked(const char * ifname);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_res_cache_init( void )
|
_res_cache_init(void)
|
||||||
{
|
{
|
||||||
const char* env = getenv(CONFIG_ENV);
|
const char* env = getenv(CONFIG_ENV);
|
||||||
|
|
||||||
|
@ -1556,29 +1604,392 @@ _res_cache_init( void )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_res_cache = _resolv_cache_create();
|
memset(&_res_default_ifname, 0, sizeof(_res_default_ifname));
|
||||||
|
memset(&_res_cache_list, 0, sizeof(_res_cache_list));
|
||||||
|
pthread_mutex_init(&_res_cache_list_lock, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct resolv_cache*
|
struct resolv_cache*
|
||||||
__get_res_cache( void )
|
__get_res_cache(void)
|
||||||
{
|
{
|
||||||
pthread_once( &_res_cache_once, _res_cache_init );
|
struct resolv_cache *cache;
|
||||||
return _res_cache;
|
|
||||||
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&_res_cache_list_lock);
|
||||||
|
|
||||||
|
char* ifname = _get_default_iface_locked();
|
||||||
|
|
||||||
|
// if default interface not set then use the first cache
|
||||||
|
// associated with an interface as the default one.
|
||||||
|
if (ifname[0] == '\0') {
|
||||||
|
struct resolv_cache_info* cache_info = _res_cache_list.next;
|
||||||
|
while (cache_info) {
|
||||||
|
if (cache_info->ifname[0] != '\0') {
|
||||||
|
ifname = cache_info->ifname;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_info = cache_info->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cache = _get_res_cache_for_iface_locked(ifname);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||||
|
XLOG("_get_res_cache. default_ifname = %s\n", ifname);
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct resolv_cache*
|
||||||
|
_get_res_cache_for_iface_locked(const char* ifname)
|
||||||
|
{
|
||||||
|
if (ifname == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct resolv_cache* cache = _find_named_cache_locked(ifname);
|
||||||
|
if (!cache) {
|
||||||
|
struct resolv_cache_info* cache_info = _create_cache_info();
|
||||||
|
if (cache_info) {
|
||||||
|
cache = _resolv_cache_create();
|
||||||
|
if (cache) {
|
||||||
|
int len = sizeof(cache_info->ifname);
|
||||||
|
cache_info->cache = cache;
|
||||||
|
strncpy(cache_info->ifname, ifname, len - 1);
|
||||||
|
cache_info->ifname[len - 1] = '\0';
|
||||||
|
|
||||||
|
_insert_cache_info_locked(cache_info);
|
||||||
|
} else {
|
||||||
|
free(cache_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_resolv_cache_reset( unsigned generation )
|
_resolv_cache_reset(unsigned generation)
|
||||||
{
|
{
|
||||||
XLOG("%s: generation=%d", __FUNCTION__, generation);
|
XLOG("%s: generation=%d", __FUNCTION__, generation);
|
||||||
|
|
||||||
if (_res_cache == NULL)
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
return;
|
pthread_mutex_lock(&_res_cache_list_lock);
|
||||||
|
|
||||||
pthread_mutex_lock( &_res_cache->lock );
|
char* ifname = _get_default_iface_locked();
|
||||||
if (_res_cache->generation != generation) {
|
// if default interface not set then use the first cache
|
||||||
_cache_flush_locked(_res_cache);
|
// associated with an interface as the default one.
|
||||||
_res_cache->generation = generation;
|
// Note: Copied the code from __get_res_cache since this
|
||||||
|
// method will be deleted/obsolete when cache per interface
|
||||||
|
// implemented all over
|
||||||
|
if (ifname[0] == '\0') {
|
||||||
|
struct resolv_cache_info* cache_info = _res_cache_list.next;
|
||||||
|
while (cache_info) {
|
||||||
|
if (cache_info->ifname[0] != '\0') {
|
||||||
|
ifname = cache_info->ifname;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_info = cache_info->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock( &_res_cache->lock );
|
struct resolv_cache* cache = _get_res_cache_for_iface_locked(ifname);
|
||||||
|
|
||||||
|
if (cache == NULL) {
|
||||||
|
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock( &cache->lock );
|
||||||
|
if (cache->generation != generation) {
|
||||||
|
_cache_flush_locked(cache);
|
||||||
|
cache->generation = generation;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock( &cache->lock );
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_resolv_flush_cache_for_default_iface(void)
|
||||||
|
{
|
||||||
|
char* ifname;
|
||||||
|
|
||||||
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
|
pthread_mutex_lock(&_res_cache_list_lock);
|
||||||
|
|
||||||
|
ifname = _get_default_iface_locked();
|
||||||
|
_flush_cache_for_iface_locked(ifname);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_resolv_flush_cache_for_iface(const char* ifname)
|
||||||
|
{
|
||||||
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
|
pthread_mutex_lock(&_res_cache_list_lock);
|
||||||
|
|
||||||
|
_flush_cache_for_iface_locked(ifname);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_flush_cache_for_iface_locked(const char* ifname)
|
||||||
|
{
|
||||||
|
struct resolv_cache* cache = _find_named_cache_locked(ifname);
|
||||||
|
if (cache) {
|
||||||
|
pthread_mutex_lock(&cache->lock);
|
||||||
|
_cache_flush_locked(cache);
|
||||||
|
pthread_mutex_unlock(&cache->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct resolv_cache_info*
|
||||||
|
_create_cache_info(void)
|
||||||
|
{
|
||||||
|
struct resolv_cache_info* cache_info;
|
||||||
|
|
||||||
|
cache_info = calloc(sizeof(*cache_info), 1);
|
||||||
|
return cache_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_insert_cache_info_locked(struct resolv_cache_info* cache_info)
|
||||||
|
{
|
||||||
|
struct resolv_cache_info* last;
|
||||||
|
|
||||||
|
for (last = &_res_cache_list; last->next; last = last->next);
|
||||||
|
|
||||||
|
last->next = cache_info;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct resolv_cache*
|
||||||
|
_find_named_cache_locked(const char* ifname) {
|
||||||
|
|
||||||
|
struct resolv_cache_info* info = _find_cache_info_locked(ifname);
|
||||||
|
|
||||||
|
if (info != NULL) return info->cache;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct resolv_cache_info*
|
||||||
|
_find_cache_info_locked(const char* ifname)
|
||||||
|
{
|
||||||
|
if (ifname == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct resolv_cache_info* cache_info = _res_cache_list.next;
|
||||||
|
|
||||||
|
while (cache_info) {
|
||||||
|
if (strcmp(cache_info->ifname, ifname) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_info = cache_info->next;
|
||||||
|
}
|
||||||
|
return cache_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
_get_default_iface_locked(void)
|
||||||
|
{
|
||||||
|
char* iface = _res_default_ifname;
|
||||||
|
|
||||||
|
return iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_resolv_set_default_iface(const char* ifname)
|
||||||
|
{
|
||||||
|
XLOG("_resolv_set_default_if ifname %s\n",ifname);
|
||||||
|
|
||||||
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
|
pthread_mutex_lock(&_res_cache_list_lock);
|
||||||
|
|
||||||
|
int size = sizeof(_res_default_ifname);
|
||||||
|
memset(_res_default_ifname, 0, size);
|
||||||
|
strncpy(_res_default_ifname, ifname, size - 1);
|
||||||
|
_res_default_ifname[size - 1] = '\0';
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_resolv_set_nameservers_for_iface(const char* ifname, char** servers, int numservers)
|
||||||
|
{
|
||||||
|
int i, rt, index;
|
||||||
|
struct addrinfo hints;
|
||||||
|
char sbuf[NI_MAXSERV];
|
||||||
|
|
||||||
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&_res_cache_list_lock);
|
||||||
|
// creates the cache if not created
|
||||||
|
_get_res_cache_for_iface_locked(ifname);
|
||||||
|
|
||||||
|
struct resolv_cache_info* cache_info = _find_cache_info_locked(ifname);
|
||||||
|
|
||||||
|
if (cache_info != NULL) {
|
||||||
|
// free current before adding new
|
||||||
|
_free_nameservers_locked(cache_info);
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = PF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
|
||||||
|
hints.ai_flags = AI_NUMERICHOST;
|
||||||
|
sprintf(sbuf, "%u", NAMESERVER_PORT);
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
for (i = 0; i < numservers && i < MAXNS; i++) {
|
||||||
|
rt = getaddrinfo(servers[i], sbuf, &hints, &cache_info->nsaddrinfo[index]);
|
||||||
|
if (rt == 0) {
|
||||||
|
cache_info->nameservers[index] = strdup(servers[i]);
|
||||||
|
index++;
|
||||||
|
} else {
|
||||||
|
cache_info->nsaddrinfo[index] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_free_nameservers_locked(struct resolv_cache_info* cache_info)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i <= MAXNS; i++) {
|
||||||
|
free(cache_info->nameservers[i]);
|
||||||
|
cache_info->nameservers[i] = NULL;
|
||||||
|
freeaddrinfo(cache_info->nsaddrinfo[i]);
|
||||||
|
cache_info->nsaddrinfo[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_resolv_cache_get_nameserver(int n, char* addr, int addrLen)
|
||||||
|
{
|
||||||
|
char *ifname;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
|
pthread_mutex_lock(&_res_cache_list_lock);
|
||||||
|
|
||||||
|
ifname = _get_default_iface_locked();
|
||||||
|
result = _get_nameserver_locked(ifname, n, addr, addrLen);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_get_nameserver_locked(const char* ifname, int n, char* addr, int addrLen)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
char* ns;
|
||||||
|
struct resolv_cache_info* cache_info;
|
||||||
|
|
||||||
|
if (n < 1 || n > MAXNS || !addr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cache_info = _find_cache_info_locked(ifname);
|
||||||
|
if (cache_info) {
|
||||||
|
ns = cache_info->nameservers[n - 1];
|
||||||
|
if (ns) {
|
||||||
|
len = strlen(ns);
|
||||||
|
if (len < addrLen) {
|
||||||
|
strncpy(addr, ns, len);
|
||||||
|
addr[len] = '\0';
|
||||||
|
} else {
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct addrinfo*
|
||||||
|
_cache_get_nameserver_addr(int n)
|
||||||
|
{
|
||||||
|
struct addrinfo *result;
|
||||||
|
char* ifname;
|
||||||
|
|
||||||
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
|
pthread_mutex_lock(&_res_cache_list_lock);
|
||||||
|
|
||||||
|
ifname = _get_default_iface_locked();
|
||||||
|
|
||||||
|
result = _get_nameserver_addr_locked(ifname, n);
|
||||||
|
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct addrinfo*
|
||||||
|
_get_nameserver_addr_locked(const char* ifname, int n)
|
||||||
|
{
|
||||||
|
struct addrinfo* ai = NULL;
|
||||||
|
struct resolv_cache_info* cache_info;
|
||||||
|
|
||||||
|
if (n < 1 || n > MAXNS)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
cache_info = _find_cache_info_locked(ifname);
|
||||||
|
if (cache_info) {
|
||||||
|
ai = cache_info->nsaddrinfo[n - 1];
|
||||||
|
}
|
||||||
|
return ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_resolv_set_addr_of_iface(const char* ifname, struct in_addr* addr)
|
||||||
|
{
|
||||||
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
|
pthread_mutex_lock(&_res_cache_list_lock);
|
||||||
|
struct resolv_cache_info* cache_info = _find_cache_info_locked(ifname);
|
||||||
|
if (cache_info) {
|
||||||
|
memcpy(&cache_info->ifaddr, addr, sizeof(*addr));
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
char* addr_s = inet_ntoa(cache_info->ifaddr);
|
||||||
|
XLOG("address of interface %s is %s\n", ifname, addr_s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct in_addr*
|
||||||
|
_resolv_get_addr_of_default_iface(void)
|
||||||
|
{
|
||||||
|
struct in_addr* ai = NULL;
|
||||||
|
char* ifname;
|
||||||
|
|
||||||
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
|
pthread_mutex_lock(&_res_cache_list_lock);
|
||||||
|
ifname = _get_default_iface_locked();
|
||||||
|
ai = _get_addr_locked(ifname);
|
||||||
|
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||||
|
|
||||||
|
return ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct in_addr*
|
||||||
|
_resolv_get_addr_of_iface(const char* ifname)
|
||||||
|
{
|
||||||
|
struct in_addr* ai = NULL;
|
||||||
|
|
||||||
|
pthread_once(&_res_cache_once, _res_cache_init);
|
||||||
|
pthread_mutex_lock(&_res_cache_list_lock);
|
||||||
|
ai =_get_addr_locked(ifname);
|
||||||
|
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||||
|
return ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct in_addr*
|
||||||
|
_get_addr_locked(const char * ifname)
|
||||||
|
{
|
||||||
|
struct resolv_cache_info* cache_info = _find_cache_info_locked(ifname);
|
||||||
|
if (cache_info) {
|
||||||
|
return &cache_info->ifaddr;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,13 +30,45 @@
|
||||||
|
|
||||||
struct resolv_cache; /* forward */
|
struct resolv_cache; /* forward */
|
||||||
|
|
||||||
/* get cache instance, can be NULL if cache is disabled
|
/* gets the cache for the default interface. Might be NULL*/
|
||||||
* (e.g. through an environment variable) */
|
|
||||||
extern struct resolv_cache* __get_res_cache(void);
|
extern struct resolv_cache* __get_res_cache(void);
|
||||||
|
|
||||||
|
/* get the cache for a specified interface. Can be NULL*/
|
||||||
|
extern struct resolv_cache* __get_res_cache_for_iface(const char* ifname);
|
||||||
|
|
||||||
/* this gets called everytime we detect some changes in the DNS configuration
|
/* this gets called everytime we detect some changes in the DNS configuration
|
||||||
* and will flush the cache */
|
* and will flush the cache */
|
||||||
extern void _resolv_cache_reset( unsigned generation );
|
extern void _resolv_cache_reset( unsigned generation );
|
||||||
|
|
||||||
|
/* Gets the address of the n:th name server for the default interface
|
||||||
|
* Return length of address on success else 0.
|
||||||
|
* Note: The first name server is at n = 1 */
|
||||||
|
extern int _resolv_cache_get_nameserver(int n, char* addr, int addrLen);
|
||||||
|
|
||||||
|
/* Gets the address of the n:th name server for a certain interface
|
||||||
|
* Return length of address on success else 0.
|
||||||
|
* Note: The first name server is at n = 1 */
|
||||||
|
extern int _resolv_cache_get_nameserver_for_iface(const char* ifname, int n,
|
||||||
|
char* addr, int addrLen);
|
||||||
|
|
||||||
|
/* Gets addrinfo of the n:th name server associated with an interface.
|
||||||
|
* NULL is returned if no address if found.
|
||||||
|
* Note: The first name server is at n = 1. */
|
||||||
|
extern struct addrinfo* _resolv_cache_get_nameserver_addr_for_iface(const char* ifname, int n);
|
||||||
|
|
||||||
|
/* Gets addrinfo of the n:th name server associated with the default interface
|
||||||
|
* NULL is returned if no address if found.
|
||||||
|
* Note: The first name server is at n = 1. */
|
||||||
|
extern struct addrinfo* _resolv_cache_get_nameserver_addr(int n);
|
||||||
|
|
||||||
|
/* gets the address associated with the default interface */
|
||||||
|
extern struct in_addr* _resolv_get_addr_of_default_iface();
|
||||||
|
|
||||||
|
/* gets the address associated with the specified interface */
|
||||||
|
extern struct in_addr* _resolv_get_addr_of_iface(const char* ifname);
|
||||||
|
|
||||||
|
/* Get name of default interface */
|
||||||
|
extern char* _resolv_get_default_iface();
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RESOLV_CACHE_UNSUPPORTED, /* the cache can't handle that kind of queries */
|
RESOLV_CACHE_UNSUPPORTED, /* the cache can't handle that kind of queries */
|
||||||
|
|
Loading…
Reference in a new issue