dns: use a dictionary for query storage
This commit is contained in:
parent
1d9925cfb3
commit
068c6c4a2b
3 changed files with 96 additions and 118 deletions
|
@ -34,12 +34,15 @@ extern rb_dlink_list nameservers;
|
||||||
typedef void (*DNSCB)(const char *res, int status, int aftype, void *data);
|
typedef void (*DNSCB)(const char *res, int status, int aftype, void *data);
|
||||||
typedef void (*DNSLISTCB)(int resc, const char *resv[], int status, void *data);
|
typedef void (*DNSLISTCB)(int resc, const char *resv[], int status, void *data);
|
||||||
|
|
||||||
uint16_t lookup_hostname(const char *hostname, int aftype, DNSCB callback, void *data);
|
uint32_t lookup_hostname(const char *hostname, int aftype, DNSCB callback, void *data);
|
||||||
uint16_t lookup_ip(const char *hostname, int aftype, DNSCB callback, void *data);
|
uint32_t lookup_ip(const char *hostname, int aftype, DNSCB callback, void *data);
|
||||||
void cancel_lookup(uint16_t xid);
|
void cancel_lookup(uint32_t xid);
|
||||||
|
void cancel_dns_stats(uint32_t xid);
|
||||||
|
|
||||||
void dns_results_callback(const char *callid, const char *status, const char *aftype, const char *results);
|
void dns_results_callback(const char *callid, const char *status, const char *aftype, const char *results);
|
||||||
void dns_stats_results_callback(const char *callid, const char *status, int resc, const char *resv[]);
|
void dns_stats_results_callback(const char *callid, const char *status, int resc, const char *resv[]);
|
||||||
void init_nameserver_cache(void);
|
|
||||||
bool reload_nameservers(void);
|
void init_dns(void);
|
||||||
|
void reload_nameservers(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
199
ircd/dns.c
199
ircd/dns.c
|
@ -45,8 +45,8 @@
|
||||||
#define DNS_REVERSE_IPV4 ((char)'R')
|
#define DNS_REVERSE_IPV4 ((char)'R')
|
||||||
#define DNS_REVERSE_IPV6 ((char)'S')
|
#define DNS_REVERSE_IPV6 ((char)'S')
|
||||||
|
|
||||||
static void submit_dns(uint16_t uid, char type, const char *addr);
|
static void submit_dns(uint32_t uid, char type, const char *addr);
|
||||||
static void submit_dns_stat(uint16_t uid);
|
static void submit_dns_stat(uint32_t uid);
|
||||||
|
|
||||||
struct dnsreq
|
struct dnsreq
|
||||||
{
|
{
|
||||||
|
@ -60,55 +60,24 @@ struct dnsstatreq
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dnsreq querytable[DNS_IDTABLE_SIZE];
|
/* These serve as a form of sparse array */
|
||||||
static struct dnsstatreq stattable[DNS_STATTABLE_SIZE];
|
static struct Dictionary *query_dict;
|
||||||
|
static struct Dictionary *stat_dict;
|
||||||
|
|
||||||
rb_dlink_list nameservers;
|
rb_dlink_list nameservers;
|
||||||
|
|
||||||
|
static uint32_t query_id = 0;
|
||||||
|
static uint32_t stat_id = 0;
|
||||||
|
|
||||||
static uint16_t
|
#define ASSIGN_ID(id) (id++)
|
||||||
assign_dns_id(void)
|
|
||||||
{
|
|
||||||
static uint16_t id = 1;
|
|
||||||
int loopcnt = 0;
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
if(++loopcnt > DNS_IDTABLE_SIZE)
|
|
||||||
return 0;
|
|
||||||
if(id < DNS_IDTABLE_SIZE - 1 || id == 0)
|
|
||||||
id++;
|
|
||||||
else
|
|
||||||
id = 1;
|
|
||||||
if(querytable[id].callback == NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return (id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t
|
|
||||||
assign_dns_stat_id(void)
|
|
||||||
{
|
|
||||||
static uint8_t id = 1;
|
|
||||||
int loopcnt = 0;
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
if(++loopcnt > DNS_STATTABLE_SIZE)
|
|
||||||
return 0;
|
|
||||||
if(id < DNS_STATTABLE_SIZE - 1 || id == 0)
|
|
||||||
id++;
|
|
||||||
else
|
|
||||||
id = 1;
|
|
||||||
if(stattable[id].callback == NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return (id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_dns_failure(uint16_t xid)
|
handle_dns_failure(uint32_t xid)
|
||||||
{
|
{
|
||||||
struct dnsreq *req;
|
struct dnsreq *req = rb_dictionary_retrieve(query_dict, RB_UINT_TO_POINTER(xid));
|
||||||
|
s_assert(req);
|
||||||
|
|
||||||
req = &querytable[xid];
|
|
||||||
if(req->callback == NULL)
|
if(req->callback == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -118,47 +87,49 @@ handle_dns_failure(uint16_t xid)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_dns_stat_failure(uint8_t xid)
|
handle_dns_stat_failure(uint32_t xid)
|
||||||
{
|
{
|
||||||
struct dnsstatreq *req;
|
struct dnsstatreq *req = rb_dictionary_retrieve(stat_dict, RB_UINT_TO_POINTER(xid));
|
||||||
const char *err[] = { "Unknown failure" };
|
s_assert(req);
|
||||||
|
|
||||||
req = &stattable[xid];
|
|
||||||
if(req->callback == NULL)
|
if(req->callback == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
req->callback(1, err, 2, req->data);
|
req->callback(1, NULL, 2, req->data);
|
||||||
|
req->callback = NULL;
|
||||||
|
req->data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
cancel_lookup(uint32_t xid)
|
||||||
|
{
|
||||||
|
struct dnsreq *req = rb_dictionary_retrieve(query_dict, RB_UINT_TO_POINTER(xid));
|
||||||
|
s_assert(req);
|
||||||
req->callback = NULL;
|
req->callback = NULL;
|
||||||
req->data = NULL;
|
req->data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cancel_lookup(uint16_t xid)
|
cancel_dns_stats(uint32_t xid)
|
||||||
{
|
{
|
||||||
querytable[xid].callback = NULL;
|
struct dnsstatreq *req = rb_dictionary_retrieve(stat_dict, RB_UINT_TO_POINTER(xid));
|
||||||
querytable[xid].data = NULL;
|
s_assert(req);
|
||||||
|
req->callback = NULL;
|
||||||
|
req->data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
cancel_dns_stats(uint16_t xid)
|
|
||||||
{
|
|
||||||
stattable[xid].callback = NULL;
|
|
||||||
stattable[xid].data = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t
|
uint32_t
|
||||||
lookup_hostname(const char *hostname, int aftype, DNSCB callback, void *data)
|
lookup_hostname(const char *hostname, int aftype, DNSCB callback, void *data)
|
||||||
{
|
{
|
||||||
struct dnsreq *req;
|
struct dnsreq *req = rb_malloc(sizeof(struct dnsreq));
|
||||||
int aft;
|
int aft;
|
||||||
uint16_t nid;
|
uint32_t rid = ASSIGN_ID(query_id);
|
||||||
check_authd();
|
|
||||||
nid = assign_dns_id();
|
|
||||||
if((nid = assign_dns_id()) == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
req = &querytable[nid];
|
check_authd();
|
||||||
|
|
||||||
|
rb_dictionary_add(query_dict, RB_UINT_TO_POINTER(rid), req);
|
||||||
|
|
||||||
req->callback = callback;
|
req->callback = callback;
|
||||||
req->data = data;
|
req->data = data;
|
||||||
|
@ -170,22 +141,20 @@ lookup_hostname(const char *hostname, int aftype, DNSCB callback, void *data)
|
||||||
#endif
|
#endif
|
||||||
aft = 4;
|
aft = 4;
|
||||||
|
|
||||||
submit_dns(nid, aft == 4 ? DNS_HOST_IPV4 : DNS_HOST_IPV6, hostname);
|
submit_dns(rid, aft == 4 ? DNS_HOST_IPV4 : DNS_HOST_IPV6, hostname);
|
||||||
return (nid);
|
return (rid);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t
|
uint32_t
|
||||||
lookup_ip(const char *addr, int aftype, DNSCB callback, void *data)
|
lookup_ip(const char *addr, int aftype, DNSCB callback, void *data)
|
||||||
{
|
{
|
||||||
struct dnsreq *req;
|
struct dnsreq *req = rb_malloc(sizeof(struct dnsreq));
|
||||||
int aft;
|
int aft;
|
||||||
uint16_t nid;
|
uint32_t rid = ASSIGN_ID(query_id);
|
||||||
|
|
||||||
check_authd();
|
check_authd();
|
||||||
|
|
||||||
if((nid = assign_dns_id()) == 0)
|
rb_dictionary_add(query_dict, RB_UINT_TO_POINTER(rid), req);
|
||||||
return 0;
|
|
||||||
|
|
||||||
req = &querytable[nid];
|
|
||||||
|
|
||||||
req->callback = callback;
|
req->callback = callback;
|
||||||
req->data = data;
|
req->data = data;
|
||||||
|
@ -197,41 +166,45 @@ lookup_ip(const char *addr, int aftype, DNSCB callback, void *data)
|
||||||
#endif
|
#endif
|
||||||
aft = 4;
|
aft = 4;
|
||||||
|
|
||||||
submit_dns(nid, aft == 4 ? DNS_REVERSE_IPV4 : DNS_REVERSE_IPV6, addr);
|
submit_dns(rid, aft == 4 ? DNS_REVERSE_IPV4 : DNS_REVERSE_IPV6, addr);
|
||||||
return (nid);
|
return (rid);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t
|
uint32_t
|
||||||
get_nameservers(DNSLISTCB callback, void *data)
|
get_nameservers(DNSLISTCB callback, void *data)
|
||||||
{
|
{
|
||||||
struct dnsstatreq *req;
|
struct dnsstatreq *req = rb_malloc(sizeof(struct dnsstatreq));
|
||||||
uint8_t nid;
|
uint32_t qid = ASSIGN_ID(stat_id);
|
||||||
|
|
||||||
check_authd();
|
check_authd();
|
||||||
|
|
||||||
if((nid = assign_dns_stat_id()) == 0)
|
rb_dictionary_add(stat_dict, RB_UINT_TO_POINTER(qid), req);
|
||||||
return 0;
|
|
||||||
|
|
||||||
req = &stattable[nid];
|
|
||||||
req->callback = callback;
|
req->callback = callback;
|
||||||
req->data = data;
|
req->data = data;
|
||||||
|
|
||||||
submit_dns_stat(nid);
|
submit_dns_stat(qid);
|
||||||
return (nid);
|
return (qid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_results_callback(const char *callid, const char *status, const char *type, const char *results)
|
dns_results_callback(const char *callid, const char *status, const char *type, const char *results)
|
||||||
{
|
{
|
||||||
struct dnsreq *req;
|
struct dnsreq *req;
|
||||||
uint16_t nid;
|
uint32_t rid;
|
||||||
int st;
|
int st;
|
||||||
int aft;
|
int aft;
|
||||||
long lnid = strtol(callid, NULL, 16);
|
long lrid = strtol(callid, NULL, 16);
|
||||||
|
|
||||||
if(lnid > DNS_IDTABLE_SIZE || lnid == 0)
|
if(lrid > UINT32_MAX)
|
||||||
return;
|
return;
|
||||||
nid = (uint16_t)lnid;
|
|
||||||
req = &querytable[nid];
|
rid = (uint32_t)lrid;
|
||||||
|
req = rb_dictionary_retrieve(query_dict, RB_UINT_TO_POINTER(rid));
|
||||||
|
if(req == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
st = (*status == 'O');
|
st = (*status == 'O');
|
||||||
aft = *type == '6' || *type == 'S' ? 6 : 4;
|
aft = *type == '6' || *type == 'S' ? 6 : 4;
|
||||||
if(req->callback == NULL)
|
if(req->callback == NULL)
|
||||||
|
@ -248,22 +221,26 @@ dns_results_callback(const char *callid, const char *status, const char *type, c
|
||||||
aft = AF_INET;
|
aft = AF_INET;
|
||||||
|
|
||||||
req->callback(results, st, aft, req->data);
|
req->callback(results, st, aft, req->data);
|
||||||
req->callback = NULL;
|
|
||||||
req->data = NULL;
|
rb_free(req);
|
||||||
|
rb_dictionary_delete(query_dict, RB_UINT_TO_POINTER(rid));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_stats_results_callback(const char *callid, const char *status, int resc, const char *resv[])
|
dns_stats_results_callback(const char *callid, const char *status, int resc, const char *resv[])
|
||||||
{
|
{
|
||||||
struct dnsstatreq *req;
|
struct dnsstatreq *req;
|
||||||
uint8_t nid;
|
uint32_t qid;
|
||||||
int st, i;
|
int st, i;
|
||||||
long lnid = strtol(callid, NULL, 16);
|
long lqid = strtol(callid, NULL, 16);
|
||||||
|
|
||||||
if(lnid > DNS_STATTABLE_SIZE || lnid == 0)
|
if(lqid > UINT32_MAX)
|
||||||
return;
|
return;
|
||||||
nid = (uint8_t)lnid;
|
|
||||||
req = &stattable[nid];
|
qid = (uint32_t)lqid;
|
||||||
|
req = rb_dictionary_retrieve(stat_dict, RB_UINT_TO_POINTER(qid));
|
||||||
|
|
||||||
|
s_assert(req);
|
||||||
|
|
||||||
if(req->callback == NULL)
|
if(req->callback == NULL)
|
||||||
{
|
{
|
||||||
|
@ -286,14 +263,14 @@ dns_stats_results_callback(const char *callid, const char *status, int resc, con
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Query complete */
|
/* Query complete */
|
||||||
req->callback(resc, resv, st, stattable[nid].data);
|
req->callback(resc, resv, st, req->data);
|
||||||
|
|
||||||
req->data = NULL;
|
rb_free(req);
|
||||||
req->callback = NULL;
|
rb_dictionary_delete(stat_dict, RB_UINT_TO_POINTER(qid));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get_nameservers_cb(int resc, const char *resv[], int status, void *data)
|
stats_results_callback(int resc, const char *resv[], int status, void *data)
|
||||||
{
|
{
|
||||||
if(status == 0)
|
if(status == 0)
|
||||||
{
|
{
|
||||||
|
@ -316,28 +293,26 @@ get_nameservers_cb(int resc, const char *resv[], int status, void *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
init_nameserver_cache(void)
|
init_dns(void)
|
||||||
{
|
{
|
||||||
(void)get_nameservers(get_nameservers_cb, NULL);
|
query_dict = rb_dictionary_create("dns queries", rb_uint32cmp);
|
||||||
|
stat_dict = rb_dictionary_create("dns stat queries", rb_uint32cmp);
|
||||||
|
(void)get_nameservers(stats_results_callback, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
reload_nameservers(void)
|
reload_nameservers(void)
|
||||||
{
|
{
|
||||||
if(authd_helper == NULL)
|
check_authd();
|
||||||
{
|
|
||||||
/* Shit */
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
rb_helper_write(authd_helper, "H D");
|
rb_helper_write(authd_helper, "H D");
|
||||||
init_nameserver_cache();
|
(void)get_nameservers(stats_results_callback, NULL);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
submit_dns(uint16_t nid, char type, const char *addr)
|
submit_dns(uint32_t nid, char type, const char *addr)
|
||||||
{
|
{
|
||||||
if(authd_helper == NULL)
|
if(authd_helper == NULL)
|
||||||
{
|
{
|
||||||
|
@ -348,7 +323,7 @@ submit_dns(uint16_t nid, char type, const char *addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
submit_dns_stat(uint16_t nid)
|
submit_dns_stat(uint32_t nid)
|
||||||
{
|
{
|
||||||
if(authd_helper == NULL)
|
if(authd_helper == NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -663,7 +663,7 @@ charybdis_main(int argc, char *argv[])
|
||||||
|
|
||||||
init_auth(); /* Initialise the auth code */
|
init_auth(); /* Initialise the auth code */
|
||||||
init_authd(); /* Start up authd. */
|
init_authd(); /* Start up authd. */
|
||||||
init_nameserver_cache(); /* Get our nameserver cache for STATS a/A */
|
init_dns(); /* Start up DNS query system */
|
||||||
|
|
||||||
privilegeset_set_new("default", "", 0);
|
privilegeset_set_new("default", "", 0);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue