dns: clean up awful hacks.

We now have a resolver cache which we init on startup.
This commit is contained in:
Elizabeth Myers 2016-03-08 03:22:25 -06:00
parent 394b8dde17
commit 8a26cd1973
4 changed files with 40 additions and 51 deletions

View file

@ -29,6 +29,8 @@
#include "stdinc.h"
#include "authd.h"
extern rb_dlink_list nameservers;
typedef void (*DNSCB)(const char *res, int status, int aftype, void *data);
typedef void (*DNSLISTCB)(int resc, const char *resv[], int status, void *data);
@ -37,6 +39,7 @@ uint16_t lookup_ip(const char *hostname, int aftype, DNSCB callback, void *data)
void cancel_lookup(uint16_t xid);
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 report_dns_servers(struct Client *, char);
void report_dns_servers(struct Client *);
void init_nameserver_cache(void);
#endif

View file

@ -60,14 +60,10 @@ struct dnsstatreq
void *data;
};
struct dnsstatreq_data
{
char uid[IDLEN];
char statchar;
};
static struct dnsreq querytable[DNS_IDTABLE_SIZE];
static struct dnsstatreq stattable[DNS_STATTABLE_SIZE];
rb_dlink_list nameservers;
static uint16_t
assign_dns_id(void)
@ -133,9 +129,6 @@ handle_dns_stat_failure(uint8_t xid)
req->callback(1, err, 2, req->data);
/* NOTE - this assumes req->data is on the heap */
rb_free(req->data);
req->callback = NULL;
req->data = NULL;
}
@ -150,9 +143,6 @@ cancel_lookup(uint16_t xid)
void
cancel_dns_stats(uint16_t xid)
{
/* NOTE - this assumes data is on the heap */
rb_free(stattable[xid].data);
stattable[xid].callback = NULL;
stattable[xid].data = NULL;
}
@ -277,8 +267,6 @@ dns_stats_results_callback(const char *callid, const char *status, int resc, con
if(req->callback == NULL)
{
/* NOTE - this assumes req->data is strdup'd or such */
rb_free(req->data);
req->data = NULL;
return;
}
@ -300,45 +288,49 @@ dns_stats_results_callback(const char *callid, const char *status, int resc, con
/* Query complete */
req->callback(resc, resv, st, stattable[nid].data);
rb_free(req->data);
req->data = NULL;
req->callback = NULL;
}
static void
report_dns_servers_cb(int resc, const char *resv[], int status, void *data)
get_nameservers_cb(int resc, const char *resv[], int status, void *data)
{
struct Client *source_p;
struct dnsstatreq_data *c_data = data;
if(!(source_p = find_id(c_data->uid)))
/* Client's gone, oh well. */
return;
if(status == 0)
{
rb_dlink_node *n, *tn;
RB_DLINK_FOREACH_SAFE(n, tn, nameservers.head)
{
/* Clean up old nameservers */
rb_free(n->data);
rb_dlinkDestroy(n, &nameservers);
}
for(int i = 0; i < resc; i++)
sendto_one_numeric(source_p, RPL_STATSDEBUG, "A %s", resv[i]);
rb_dlinkAddAlloc(rb_strdup(resv[i]), &nameservers);
}
else
{
if(resc && resv[resc][0])
/* XXX is this the right reply? */
sendto_one_numeric(source_p, RPL_STATSDEBUG, "A Error: %s", resv[resc]);
const char *error = resc ? resv[resc] : "Unknown error";
iwarn(L_MAIN, "Error getting DNS servers: %s", error);
}
sendto_one_numeric(source_p, RPL_ENDOFSTATS, form_str(RPL_ENDOFSTATS), c_data->statchar);
}
void
report_dns_servers(struct Client *source_p, char statchar)
report_dns_servers(struct Client *source_p)
{
/* Use the UID to avoid a race where source_p goes away */
struct dnsstatreq_data *data = rb_malloc(sizeof(struct dnsstatreq_data));
rb_strlcpy(data->uid, source_p->id, IDLEN);
data->statchar = statchar;
rb_dlink_node *n;
get_nameservers(report_dns_servers_cb, data);
RB_DLINK_FOREACH(n, nameservers.head)
{
sendto_one_numeric(source_p, RPL_STATSDEBUG, "A %s", (char *)n->data);
}
}
void
init_nameserver_cache(void)
{
(void)get_nameservers(get_nameservers_cb, NULL);
}
static void

View file

@ -663,6 +663,8 @@ charybdis_main(int argc, char *argv[])
init_auth(); /* Initialise the auth code */
init_authd(); /* Start up authd. */
init_nameserver_cache(); /* Get our nameserver cache for STATS a/A */
privilegeset_set_new("default", "", 0);
if (testing_conf)

View file

@ -89,7 +89,7 @@ struct StatsStruct
int need_admin;
};
static void stats_dns_servers(struct Client *, char);
static void stats_dns_servers(struct Client *);
static void stats_delay(struct Client *);
static void stats_hash(struct Client *);
static void stats_connect(struct Client *);
@ -132,8 +132,8 @@ static void stats_capability(struct Client *);
*/
static struct StatsStruct stats_cmd_table[] = {
/* letter function need_oper need_admin */
{'a', NULL /* special */, 1, 1, },
{'A', NULL /* special */, 1, 1, },
{'a', stats_dns_servers, 1, 1, },
{'A', stats_dns_servers, 1, 1, },
{'b', stats_delay, 1, 1, },
{'B', stats_hash, 1, 1, },
{'c', stats_connect, 0, 0, },
@ -219,7 +219,7 @@ m_stats(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
if(hunt_server (client_p, source_p, ":%s STATS %s :%s", 2, parc, parv) != HUNTED_ISME)
return 0;
if((statchar != 'L') && (statchar != 'l') && (statchar != 'A') && (statchar != 'a'))
if((statchar != 'L') && (statchar != 'l'))
did_stats = stats_spy(source_p, statchar, NULL);
/* if did_stats is true, a module grabbed this STATS request */
@ -247,17 +247,9 @@ m_stats(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
break;
}
/* Blah, stats L needs the parameters, none of the others do.. */
if(statchar == 'L' || statchar == 'l')
{
/* Blah, stats L needs the parameters, none of the others do.. */
stats_ltrace (source_p, parc, parv);
}
else if(statchar == 'a' || statchar == 'A')
{
/* Need to suppress RPL_ENDOFSTATS since this is an async call */
stats_dns_servers(source_p, statchar);
return 0;
}
else
stats_cmd_table[i].handler (source_p);
}
@ -272,9 +264,9 @@ stats_out:
}
static void
stats_dns_servers (struct Client *source_p, char statchar)
stats_dns_servers (struct Client *source_p)
{
report_dns_servers (source_p, statchar);
report_dns_servers (source_p);
}
static void