mirror of
https://github.com/libevent/libevent.git
synced 2025-01-09 00:56:20 +08:00
evdns: add ability to get CNAME
Add new flag (DNS_CNAME_CALLBACK) for evdns_base_resolve_ipv4()/evdns_base_resolve_ipv6(). If set, you will get one more callback with type == DNS_CNAME and CNAME in addrs argument.
This commit is contained in:
parent
087bbc572c
commit
19b3fd0bf0
31
evdns.c
31
evdns.c
@ -209,6 +209,7 @@ struct request {
|
||||
u16 trans_id; /* the transaction id */
|
||||
unsigned request_appended :1; /* true if the request pointer is data which follows this struct */
|
||||
unsigned transmit_me :1; /* needs to be transmitted */
|
||||
unsigned need_cname :1; /* make a separate callback for CNAME */
|
||||
|
||||
/* XXXX This is a horrible hack. */
|
||||
char **put_cname_in_ptr; /* store the cname here if we get one. */
|
||||
@ -228,6 +229,7 @@ struct reply {
|
||||
char *ptr_name;
|
||||
void *raw;
|
||||
} data;
|
||||
char *cname;
|
||||
};
|
||||
|
||||
enum tcp_state {
|
||||
@ -986,12 +988,15 @@ reply_run_callback(struct event_callback *d, void *user_pointer)
|
||||
|
||||
switch (cb->request_type) {
|
||||
case TYPE_A:
|
||||
if (cb->have_reply)
|
||||
if (cb->have_reply) {
|
||||
cb->user_callback(DNS_ERR_NONE, DNS_IPv4_A,
|
||||
cb->reply.rr_count, cb->ttl,
|
||||
cb->reply.data.a,
|
||||
user_pointer);
|
||||
else
|
||||
if (cb->reply.cname)
|
||||
cb->user_callback(DNS_ERR_NONE, DNS_CNAME, 1,
|
||||
cb->ttl, cb->reply.cname, user_pointer);
|
||||
} else
|
||||
cb->user_callback(cb->err, 0, 0, cb->ttl, NULL, user_pointer);
|
||||
break;
|
||||
case TYPE_PTR:
|
||||
@ -1004,12 +1009,15 @@ reply_run_callback(struct event_callback *d, void *user_pointer)
|
||||
}
|
||||
break;
|
||||
case TYPE_AAAA:
|
||||
if (cb->have_reply)
|
||||
if (cb->have_reply) {
|
||||
cb->user_callback(DNS_ERR_NONE, DNS_IPv6_AAAA,
|
||||
cb->reply.rr_count, cb->ttl,
|
||||
cb->reply.data.aaaa,
|
||||
user_pointer);
|
||||
else
|
||||
if (cb->reply.cname)
|
||||
cb->user_callback(DNS_ERR_NONE, DNS_CNAME, 1,
|
||||
cb->ttl, cb->reply.cname, user_pointer);
|
||||
} else
|
||||
cb->user_callback(cb->err, 0, 0, cb->ttl, NULL, user_pointer);
|
||||
break;
|
||||
default:
|
||||
@ -1024,6 +1032,10 @@ reply_run_callback(struct event_callback *d, void *user_pointer)
|
||||
mm_free(cb->reply.data.raw);
|
||||
}
|
||||
|
||||
if (cb->reply.cname) {
|
||||
mm_free(cb->reply.cname);
|
||||
}
|
||||
|
||||
mm_free(cb);
|
||||
}
|
||||
|
||||
@ -1383,13 +1395,13 @@ reply_parse(struct evdns_base *base, u8 *packet, int length)
|
||||
break;
|
||||
} else if (type == TYPE_CNAME) {
|
||||
char cname[HOST_NAME_MAX];
|
||||
if (!req->put_cname_in_ptr || *req->put_cname_in_ptr) {
|
||||
j += datalength; continue;
|
||||
}
|
||||
if (name_parse(packet, length, &j, cname,
|
||||
sizeof(cname))<0)
|
||||
goto err;
|
||||
*req->put_cname_in_ptr = mm_strdup(cname);
|
||||
if (req->need_cname)
|
||||
reply.cname = mm_strdup(cname);
|
||||
if (req->put_cname_in_ptr && !*req->put_cname_in_ptr)
|
||||
*req->put_cname_in_ptr = mm_strdup(cname);
|
||||
} else if (type == TYPE_AAAA && class == CLASS_INET) {
|
||||
int addrcount;
|
||||
if (req->request_type != TYPE_AAAA) {
|
||||
@ -3555,6 +3567,9 @@ request_new(struct evdns_base *base, struct evdns_request *handle, int type,
|
||||
handle->base = base;
|
||||
}
|
||||
|
||||
if (flags & DNS_CNAME_CALLBACK)
|
||||
req->need_cname = 1;
|
||||
|
||||
return req;
|
||||
err1:
|
||||
mm_free(req);
|
||||
|
@ -182,6 +182,7 @@ extern "C" {
|
||||
#define DNS_IPv4_A 1
|
||||
#define DNS_PTR 2
|
||||
#define DNS_IPv6_AAAA 3
|
||||
#define DNS_CNAME 4
|
||||
|
||||
/** Disable searching for the query. */
|
||||
#define DNS_QUERY_NO_SEARCH 0x01
|
||||
@ -189,6 +190,8 @@ extern "C" {
|
||||
#define DNS_QUERY_USEVC 0x02
|
||||
/** Ignore trancation flag in responses (don't fallback to TCP connections). */
|
||||
#define DNS_QUERY_IGNTC 0x04
|
||||
/** Make a separate callback for CNAME in answer */
|
||||
#define DNS_CNAME_CALLBACK 0x80
|
||||
|
||||
/* Allow searching */
|
||||
#define DNS_OPTION_SEARCH 1
|
||||
|
@ -512,7 +512,7 @@ generic_dns_callback(int result, char type, int count, int ttl, void *addresses,
|
||||
len = count * 4;
|
||||
else if (type == DNS_IPv6_AAAA)
|
||||
len = count * 16;
|
||||
else if (type == DNS_PTR)
|
||||
else if (type == DNS_PTR || type == DNS_CNAME)
|
||||
len = strlen(addresses)+1;
|
||||
else {
|
||||
res->addrs_len = len = 0;
|
||||
@ -551,6 +551,7 @@ static struct regress_dns_server_table search_table[] = {
|
||||
{ "hostn.a.example.com", "errsoa", "0", 0, 0 },
|
||||
{ "hostn.b.example.com", "errsoa", "3", 0, 0 },
|
||||
{ "hostn.c.example.com", "err", "0", 0, 0 },
|
||||
{ "hostc.c.example.com", "CNAME", "cname.c.example.com", 0, 0 },
|
||||
{ "host", "err", "3", 0, 0 },
|
||||
{ "host2", "err", "3", 0, 0 },
|
||||
{ "*", "err", "3", 0, 0 },
|
||||
@ -586,7 +587,7 @@ dns_search_test_impl(void *arg, int lower)
|
||||
ev_uint16_t portnum = 0;
|
||||
char buf[64];
|
||||
|
||||
struct generic_dns_callback_result r[8];
|
||||
struct generic_dns_callback_result r[9];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(table); ++i) {
|
||||
@ -604,7 +605,7 @@ dns_search_test_impl(void *arg, int lower)
|
||||
evdns_base_search_add(dns, "b.example.com");
|
||||
evdns_base_search_add(dns, "c.example.com");
|
||||
|
||||
n_replies_left = ARRAY_SIZE(r);
|
||||
n_replies_left = ARRAY_SIZE(r)+1; /* CNAME gives us 2 callbacks for 1 request */
|
||||
exit_base = base;
|
||||
|
||||
evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r[0]);
|
||||
@ -615,6 +616,8 @@ dns_search_test_impl(void *arg, int lower)
|
||||
evdns_base_resolve_ipv4(dns, "hostn.a.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[5]);
|
||||
evdns_base_resolve_ipv4(dns, "hostn.b.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[6]);
|
||||
evdns_base_resolve_ipv4(dns, "hostn.c.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[7]);
|
||||
evdns_base_resolve_ipv4(dns, "hostc.c.example.com", DNS_NO_SEARCH | DNS_CNAME_CALLBACK,
|
||||
generic_dns_callback, &r[8]);
|
||||
|
||||
event_base_dispatch(base);
|
||||
|
||||
@ -633,6 +636,9 @@ dns_search_test_impl(void *arg, int lower)
|
||||
tt_int_op(r[6].ttl, ==, 42);
|
||||
tt_int_op(r[7].result, ==, DNS_ERR_NODATA);
|
||||
tt_int_op(r[7].ttl, ==, 0);
|
||||
tt_int_op(r[8].type, ==, DNS_CNAME);
|
||||
tt_int_op(r[8].count, ==, 1);
|
||||
tt_str_op(r[8].addrs, ==, "cname.c.example.com");
|
||||
|
||||
end:
|
||||
if (dns)
|
||||
|
@ -257,6 +257,11 @@ regress_dns_server_cb(struct evdns_server_request *req, void *data)
|
||||
}
|
||||
evdns_server_request_add_aaaa_reply(req,
|
||||
question, 1, &in6.s6_addr, 100);
|
||||
} else if (!strcmp(tab->anstype, "CNAME")) {
|
||||
struct in_addr in;
|
||||
evutil_inet_pton(AF_INET, "11.22.33.44", &in);
|
||||
evdns_server_request_add_a_reply(req, question, 1, &in, 100);
|
||||
evdns_server_request_add_cname_reply(req, question, tab->ans, 100);
|
||||
} else {
|
||||
TT_DIE(("Weird table entry with type '%s'", tab->anstype));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user