mirror of https://github.com/getdnsapi/getdns.git
Add OPT Record parsing support
This commit is contained in:
parent
b84c13748c
commit
22fa1101bb
162
src/rr-dict.c
162
src/rr-dict.c
|
@ -1221,3 +1221,165 @@ priv_getdns_create_rr_from_dict(struct getdns_dict *rr_dict, ldns_rr **rr)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getdns_return_t
|
||||||
|
priv_getdns_get_opt_dict(struct getdns_context* context,
|
||||||
|
struct getdns_dict** record_dict, uint8_t* record_start,
|
||||||
|
size_t* bytes_remaining, size_t* bytes_parsed) {
|
||||||
|
|
||||||
|
getdns_return_t r = GETDNS_RETURN_GOOD;
|
||||||
|
struct getdns_dict* opt = NULL;
|
||||||
|
uint16_t code;
|
||||||
|
struct getdns_bindata opt_data;
|
||||||
|
if (*bytes_remaining < 4) {
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
code = ldns_read_uint16(record_start);
|
||||||
|
opt_data.size = ldns_read_uint16(record_start + 2);
|
||||||
|
if (*bytes_remaining < (4 + opt_data.size)) {
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
opt = getdns_dict_create_with_context(context);
|
||||||
|
if (!opt) {
|
||||||
|
return GETDNS_RETURN_MEMORY_ERROR;
|
||||||
|
}
|
||||||
|
/* set code */
|
||||||
|
r = getdns_dict_set_int(opt, opt_rdata[1].name, code);
|
||||||
|
if (r != GETDNS_RETURN_GOOD) {
|
||||||
|
getdns_dict_destroy(opt);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
/* set data */
|
||||||
|
opt_data.data = record_start + 4;
|
||||||
|
getdns_dict_set_bindata(opt, opt_rdata[2].name, &opt_data);
|
||||||
|
if (r != GETDNS_RETURN_GOOD) {
|
||||||
|
getdns_dict_destroy(opt);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
/* set result data */
|
||||||
|
*bytes_remaining = *bytes_remaining - (4 + opt_data.size);
|
||||||
|
*bytes_parsed = *bytes_parsed + (4 + opt_data.size);
|
||||||
|
*record_dict = opt;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getdns_return_t
|
||||||
|
priv_getdns_create_opt_rr(
|
||||||
|
struct getdns_context *context, ldns_rdf* rdf,
|
||||||
|
struct getdns_dict** rr_dict) {
|
||||||
|
|
||||||
|
struct getdns_dict* result = NULL;
|
||||||
|
getdns_return_t r = GETDNS_RETURN_GOOD;
|
||||||
|
size_t bytes_remaining = ldns_rdf_size(rdf);
|
||||||
|
size_t bytes_parsed = 0;
|
||||||
|
uint8_t* record_start = ldns_rdf_data(rdf);
|
||||||
|
struct getdns_list* records = getdns_list_create_with_context(context);
|
||||||
|
size_t idx = 0;
|
||||||
|
if (!records) {
|
||||||
|
return GETDNS_RETURN_MEMORY_ERROR;
|
||||||
|
}
|
||||||
|
while (r == GETDNS_RETURN_GOOD && bytes_remaining > 0) {
|
||||||
|
struct getdns_dict* opt = NULL;
|
||||||
|
r = priv_getdns_get_opt_dict(context, &opt,
|
||||||
|
record_start + bytes_parsed, &bytes_remaining,
|
||||||
|
&bytes_parsed);
|
||||||
|
if (r == GETDNS_RETURN_GOOD) {
|
||||||
|
getdns_list_set_dict(records, idx, opt);
|
||||||
|
getdns_dict_destroy(opt);
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (r != GETDNS_RETURN_GOOD) {
|
||||||
|
getdns_list_destroy(records);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
result = getdns_dict_create_with_context(context);
|
||||||
|
if (!result) {
|
||||||
|
getdns_list_destroy(records);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
/* cheat */
|
||||||
|
r = 0;
|
||||||
|
r |= getdns_dict_set_list(result,
|
||||||
|
opt_rdata[0].name, records);
|
||||||
|
getdns_list_destroy(records);
|
||||||
|
|
||||||
|
/* does class makes sense? */
|
||||||
|
if (r != GETDNS_RETURN_GOOD) {
|
||||||
|
getdns_dict_destroy(result);
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
*rr_dict = result;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
getdns_return_t priv_getdns_append_opt_rr(
|
||||||
|
struct getdns_context *context, struct getdns_list* rdatas, ldns_pkt* pkt) {
|
||||||
|
struct getdns_dict* opt_rr;
|
||||||
|
struct getdns_dict* rr_dict;
|
||||||
|
getdns_return_t r = 0;
|
||||||
|
struct getdns_bindata rdata;
|
||||||
|
ldns_rdf* edns_data = ldns_pkt_edns_data(pkt);
|
||||||
|
uint8_t rdata_buf[65536];
|
||||||
|
size_t list_len;
|
||||||
|
if (!edns_data) {
|
||||||
|
/* nothing to do */
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
r = getdns_list_get_length(rdatas, &list_len);
|
||||||
|
if (r != GETDNS_RETURN_GOOD) {
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
r = priv_getdns_create_opt_rr(context, edns_data,
|
||||||
|
&opt_rr);
|
||||||
|
if (r != GETDNS_RETURN_GOOD) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
/* size is: 0 label, 2 byte type, 2 byte class (size),
|
||||||
|
4 byte ttl, 2 byte opt len + data itself */
|
||||||
|
rdata.size = 11 + ldns_rdf_size(edns_data);
|
||||||
|
rdata.data = rdata_buf;
|
||||||
|
rdata_buf[0] = 0;
|
||||||
|
ldns_write_uint16(rdata_buf + 1, LDNS_RR_TYPE_OPT);
|
||||||
|
ldns_write_uint16(rdata_buf + 3, ldns_pkt_edns_udp_size(pkt));
|
||||||
|
rdata_buf[5] = ldns_pkt_edns_extended_rcode(pkt);
|
||||||
|
rdata_buf[6] = ldns_pkt_edns_version(pkt);
|
||||||
|
ldns_write_uint16(rdata_buf + 7, ldns_pkt_edns_z(pkt));
|
||||||
|
ldns_write_uint16(rdata_buf + 9, ldns_rdf_size(edns_data));
|
||||||
|
memcpy(rdata_buf + 11, ldns_rdf_data(edns_data), ldns_rdf_size(edns_data));
|
||||||
|
|
||||||
|
/* add data */
|
||||||
|
r |= getdns_dict_set_bindata(opt_rr, "rdata_raw", &rdata);
|
||||||
|
if (r != GETDNS_RETURN_GOOD) {
|
||||||
|
getdns_dict_destroy(opt_rr);
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rr_dict = getdns_dict_create_with_context(context);
|
||||||
|
if (!rr_dict) {
|
||||||
|
getdns_dict_destroy(opt_rr);
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
r = getdns_dict_set_dict(rr_dict, "rdata", opt_rr);
|
||||||
|
getdns_dict_destroy(opt_rr);
|
||||||
|
if (r != GETDNS_RETURN_GOOD) {
|
||||||
|
getdns_dict_destroy(rr_dict);
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
r = getdns_dict_set_int(rr_dict, "type", GETDNS_RRTYPE_OPT);
|
||||||
|
if (r != GETDNS_RETURN_GOOD) {
|
||||||
|
getdns_dict_destroy(rr_dict);
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
/* other fields don't really make sense as they are
|
||||||
|
interpreted differently */
|
||||||
|
|
||||||
|
/* append */
|
||||||
|
r = getdns_list_set_dict(rdatas, list_len, opt_rr);
|
||||||
|
getdns_dict_destroy(opt_rr);
|
||||||
|
if (r != GETDNS_RETURN_GOOD) {
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,9 @@ getdns_return_t priv_getdns_create_rr_from_dict(
|
||||||
|
|
||||||
const char *priv_getdns_rr_type_name(int rr_type);
|
const char *priv_getdns_rr_type_name(int rr_type);
|
||||||
|
|
||||||
|
getdns_return_t priv_getdns_append_opt_rr(
|
||||||
|
struct getdns_context *context, struct getdns_list* rdatas, ldns_pkt* pkt);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* rrs.h */
|
/* rrs.h */
|
||||||
|
|
|
@ -464,11 +464,14 @@ create_reply_dict(struct getdns_context *context, getdns_network_req * req,
|
||||||
/* additional */
|
/* additional */
|
||||||
rr_list = ldns_pkt_additional(reply);
|
rr_list = ldns_pkt_additional(reply);
|
||||||
sublist = create_list_from_rr_list(context, rr_list);
|
sublist = create_list_from_rr_list(context, rr_list);
|
||||||
r = getdns_dict_set_list(result, GETDNS_STR_KEY_ADDITIONAL, sublist);
|
if (sublist) {
|
||||||
|
r |= priv_getdns_append_opt_rr(context, sublist, reply);
|
||||||
|
r |= getdns_dict_set_list(result, GETDNS_STR_KEY_ADDITIONAL, sublist);
|
||||||
getdns_list_destroy(sublist);
|
getdns_list_destroy(sublist);
|
||||||
if (r != GETDNS_RETURN_GOOD) {
|
if (r != GETDNS_RETURN_GOOD) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* other stuff */
|
/* other stuff */
|
||||||
r = getdns_dict_set_int(result, GETDNS_STR_KEY_ANSWER_TYPE,
|
r = getdns_dict_set_int(result, GETDNS_STR_KEY_ANSWER_TYPE,
|
||||||
|
|
Loading…
Reference in New Issue