Repeating and special rdata field 2 wireformat

This commit is contained in:
Willem Toorop 2015-12-15 00:07:05 +01:00
parent 0433c47466
commit b0aae6b51d
4 changed files with 302 additions and 62 deletions

View File

@ -487,7 +487,7 @@ static getdns_return_t
hip_public_key_2wire(
const getdns_bindata *value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
{
if (rdata > rdf - 4 || rdata + rdata[1] != rdf)
if (rdata > rdf - 4 || rdata + 4 + rdata[0] != rdf)
return GETDNS_RETURN_GENERIC_ERROR;
if (value && value->size > 0xFFFF)
return GETDNS_RETURN_INVALID_PARAMETER;
@ -1057,74 +1057,109 @@ write_bindata_rdata(gldns_buffer *buf,
static getdns_return_t
write_rdata_field(gldns_buffer *buf,
_getdns_rdf_type type, const char *name, getdns_dict *rdata)
write_rdata_field(gldns_buffer *buf, uint8_t *rdata_start,
const _getdns_rdata_def *rd_def, getdns_dict *rdata)
{
getdns_return_t r;
getdns_list *list;
uint32_t value;
getdns_bindata *bindata;
size_t i;
size_t i, rdf_len;
if (type & GETDNS_RDF_INTEGER) {
if (!(type & GETDNS_RDF_REPEAT)) {
if ((r = getdns_dict_get_int(rdata, name, &value)))
if (rd_def->type & GETDNS_RDF_INTEGER) {
if (!(rd_def->type & GETDNS_RDF_REPEAT)) {
if ((r = getdns_dict_get_int(
rdata, rd_def->name, &value)))
return r;
else
write_int_rdata(buf, type, value);
write_int_rdata(buf, rd_def->type, value);
} else if ((r = getdns_dict_get_list(rdata, name, &list)))
return r;
} else if ((r = getdns_dict_get_list(
rdata, rd_def->name, &list)))
return r == GETDNS_RETURN_NO_SUCH_DICT_NAME
? GETDNS_RETURN_GOOD : r;
else for ( i = 0
; GETDNS_RETURN_GOOD ==
(r = getdns_list_get_int(list, i, &value))
; i++)
write_int_rdata(buf, type, value);
write_int_rdata(buf, rd_def->type, value);
if (r != GETDNS_RETURN_NO_SUCH_LIST_ITEM)
return r;
} else if (type & GETDNS_RDF_BINDATA) {
if (!(type & GETDNS_RDF_REPEAT)) {
if ((r = getdns_dict_get_bindata(rdata,name,&bindata)))
} else if (rd_def->type & GETDNS_RDF_BINDATA) {
if (!(rd_def->type & GETDNS_RDF_REPEAT)) {
if ((r = getdns_dict_get_bindata(
rdata, rd_def->name, &bindata)))
return r;
else
write_bindata_rdata(buf, type, bindata);
write_bindata_rdata(buf, rd_def->type, bindata);
} else if ((r = getdns_dict_get_list(rdata, name, &list)))
return r;
} else if ((r = getdns_dict_get_list(
rdata, rd_def->name, &list)))
return r == GETDNS_RETURN_NO_SUCH_DICT_NAME
? GETDNS_RETURN_GOOD : r;
else for ( i = 0
; GETDNS_RETURN_GOOD ==
(r = getdns_list_get_bindata(list, i, &bindata))
; i++)
write_bindata_rdata(buf, type, bindata);
write_bindata_rdata(buf, rd_def->type, bindata);
if (r != GETDNS_RETURN_NO_SUCH_LIST_ITEM)
return r;
} else
/* TODO: Handle the special types */
} else if (!(rd_def->type & GETDNS_RDF_SPECIAL)) {
/* Unknown rdata type */
return GETDNS_RETURN_GENERIC_ERROR;
return GETDNS_RETURN_GOOD;
} else if (!(rd_def->type & GETDNS_RDF_REPEAT)) {
rdf_len = gldns_buffer_remaining(buf);
r = rd_def->special->dict2wire(rdata, rdata_start,
gldns_buffer_current(buf), &rdf_len);
if (r == GETDNS_RETURN_GOOD ||
r == GETDNS_RETURN_NEED_MORE_SPACE)
gldns_buffer_skip(buf, rdf_len);
if (r)
return r;
} else if ((r = getdns_dict_get_list(rdata, rd_def->name, &list))) {
return r == GETDNS_RETURN_NO_SUCH_DICT_NAME
? GETDNS_RETURN_GOOD : r;
} else for ( i = 0; r == GETDNS_RETURN_GOOD; i++ ) {
rdf_len = gldns_buffer_remaining(buf);
r = rd_def->special->list2wire(list, i, rdata_start,
gldns_buffer_current(buf), &rdf_len);
if (r == GETDNS_RETURN_GOOD ||
r == GETDNS_RETURN_NEED_MORE_SPACE)
gldns_buffer_skip(buf, rdf_len);
}
return r != GETDNS_RETURN_NO_SUCH_LIST_ITEM ? r : GETDNS_RETURN_GOOD;
}
getdns_return_t
_getdns_rr_dict2wire(const getdns_dict *rr_dict, gldns_buffer *buf)
{
getdns_return_t r = GETDNS_RETURN_GOOD;
struct getdns_bindata *name;
struct getdns_bindata *rdata_raw;
struct getdns_dict *rdata;
getdns_bindata *name;
getdns_bindata *rdata_raw;
getdns_dict *rdata;
uint32_t rr_type;
uint32_t rr_class = GETDNS_RRCLASS_IN;
uint32_t rr_ttl = 0;
const _getdns_rr_def *rr_def;
const _getdns_rdata_def *rd_def;
int n_rdata_fields;
const _getdns_rdata_def *rd_def, *rep_rd_def;
int n_rdata_fields, rep_n_rdata_fields;
size_t rdata_size_mark;
uint8_t *rdata_start;
getdns_list *list;
size_t i;
assert(rr_dict);
assert(buf);
@ -1166,20 +1201,47 @@ _getdns_rr_dict2wire(const getdns_dict *rr_dict, gldns_buffer *buf)
} else if (n_rdata_fields || r == GETDNS_RETURN_NO_SUCH_DICT_NAME) {
r = GETDNS_RETURN_GOOD;
rdata_size_mark = gldns_buffer_position(buf);
gldns_buffer_skip(buf, 2);
rdata_start = gldns_buffer_current(buf);
for ( rd_def = rr_def->rdata
, n_rdata_fields = rr_def->n_rdata_fields
; n_rdata_fields ; n_rdata_fields-- , rd_def++ ) {
if (rd_def->type == GETDNS_RDF_REPEAT)
break;
if (rd_def->type != GETDNS_RDF_REPEAT) {
if ((r = write_rdata_field(
buf, rd_def->type, rd_def->name, rdata)))
if ((r = write_rdata_field(buf,
rdata_start, rd_def, rdata)))
break;
}
if (n_rdata_fields == 0 || r) {
/* pass */;
} else if ((r = getdns_dict_get_list(
rdata, rd_def->name, &list))) {
/* pass */;
} else for ( i = 0
; r == GETDNS_RETURN_GOOD
; i++) {
if ((r = getdns_list_get_dict(list, i, &rdata))) {
if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM)
r = GETDNS_RETURN_GOOD;
break;
}
/* TODO: Deal with repeat blocks */
for ( rep_rd_def = rd_def + 1
, rep_n_rdata_fields = n_rdata_fields - 1
; rep_n_rdata_fields
; rep_n_rdata_fields--, rep_rd_def++ ) {
if ((r = write_rdata_field(buf,
rdata_start, rep_rd_def, rdata)))
break;
}
}
gldns_buffer_write_u16_at(buf, rdata_size_mark,
(uint16_t)(gldns_buffer_position(buf)-rdata_size_mark-2));

View File

@ -132,15 +132,15 @@ typedef enum _getdns_rdf_wf_type {
} _getdns_rdf_type;
typedef struct _getdns_rdata_def {
const char *name;
const char *name;
_getdns_rdf_type type;
_getdns_rdf_special *special;
} _getdns_rdata_def;
typedef struct _getdns_rr_def {
const char *name;
const char *name;
const _getdns_rdata_def *rdata;
int n_rdata_fields;
int n_rdata_fields;
} _getdns_rr_def;
const _getdns_rr_def *_getdns_rr_def_lookup(uint16_t rr_type);

View File

@ -54,38 +54,91 @@ int main()
getdns_dict *rr_dict;
getdns_bindata *dns_name;
getdns_bindata address = { 4, "\xb9\x31\x8d\x25" };
getdns_bindata nothing = { 8, "\x07nothing" };
getdns_bindata fourth = { 11, "last string" };
size_t length;
getdns_list *list;
char *str;
uint8_t wire_buf[4096], *wire = wire_buf, *end_of_wire;
size_t wire_len = sizeof(wire_buf);
size_t wire_len;
/* Convert string to rr_dict
*/
if ((r = getdns_str2rr_dict(
"some.domain.tld. 60 CH TXT \"first string\" second \"and third\"",
"some.domain.tld. 60 IN TXT \"first string\" second \"and third\"",
&rr_dict, NULL, 3600)))
FAIL_r("getdns_str2rr_dict");
/* Add a fourth text element.
*/
if ((r = getdns_dict_set_bindata(rr_dict, "/rdata/txt_strings/-", &fourth)))
FAIL_r("getdns_list_set_bindata");
print_dict(rr_dict);
/* Convert to wireformat from rdata_raw.
* Added fourth list element should NOT show.
*/
wire_len = sizeof(wire_buf);
if ((r = getdns_rr_dict2wire(rr_dict, wire, &wire_len)))
FAIL_r("getdns_rr_dict2wire");
print_wire(wire, wire_len);
/* Convert to wireformat from parsing rdata fields.
* Added fourth list element should show.
*/
if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rdata_raw")))
FAIL_r("getdns_dict_remove_name");
print_dict(rr_dict);
printf("\nremoved \"/rdata/rdata_raw\":\n\n");
wire_len = sizeof(wire_buf);
if ((r = getdns_rr_dict2wire(rr_dict, wire, &wire_len)))
FAIL_r("getdns_rr_dict2wire");
print_wire(wire, wire_len);
/* Remove second and third string elements and show text format.
*/
if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/1")))
FAIL_r("getdns_dict_remove_name");
if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/1")))
FAIL_r("getdns_dict_remove_name");
if ((r = getdns_rr_dict2str(rr_dict, &str)))
FAIL_r("getdns_rr_dict2str");
printf("\n%s", str);
free(str);
/* Remove all string elements and show text format.
*/
if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/0")))
FAIL_r("getdns_dict_remove_name");
if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/0")))
FAIL_r("getdns_dict_remove_name");
if ((r = getdns_rr_dict2str(rr_dict, &str)))
FAIL_r("getdns_rr_dict2str");
printf("%s", str);
free(str);
getdns_dict_destroy(rr_dict);
/* Forward wireformat to test scanning from wireformat later on
*/
wire += wire_len;
wire_len = sizeof(wire_buf) - (wire - wire_buf);
/* Construct rr_dict and convert to string
*/
if (!(rr_dict = getdns_dict_create()))
FAIL("getdns_dict_create returned NULL");
@ -108,6 +161,7 @@ int main()
FAIL_r("getdns_rr_dict2str");
printf("\n%s\n", str);
free(str);
if ((r = getdns_rr_dict2wire(rr_dict, wire, &wire_len)))
FAIL_r("getdns_rr_dict2wire");
@ -118,6 +172,73 @@ int main()
wire += wire_len;
wire_len = sizeof(wire_buf) - (wire - wire_buf);
/* Convert RR with special rdata fields and repeating last element
* from string to rr_dict
*/
if ((r = getdns_str2rr_dict(
"hip2 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs1.example.com. rvs2.example.com.",
&rr_dict, "nlnetlabs.nl", 3600)))
FAIL_r("getdns_str2rr_dict");
if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rdata_raw")))
FAIL_r("getdns_dict_remove_name");
printf("\n");
print_dict(rr_dict);
/* Convert RR with special rdata fields and repeating last element
* back to string.
*/
if ((r = getdns_rr_dict2str(rr_dict, &str)))
FAIL_r("getdns_rr_dict2str");
printf("%s", str);
free(str);
/* Convert RR with special rdata fields without repeating last element
* to string.
*/
if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rendezvous_servers")))
FAIL_r("getdns_dict_remove_name");
if ((r = getdns_dict_get_bindata(rr_dict, "name", &dns_name)))
FAIL_r("getdns_dict_get_bindata");
dns_name->data[4] = '0';
if ((r = getdns_rr_dict2str(rr_dict, &str)))
FAIL_r("getdns_rr_dict2str");
printf("%s\n", str);
free(str);
getdns_dict_destroy(rr_dict);
/* Convert RR with repeat block from string to rr_dict
*/
if ((r = getdns_str2rr_dict(
"apl APL 1:192.168.42.0/26 1:192.168.42.64/26 !1:192.168.42.128/25 1:224.0.0.0/4 2:FF00:0:0:0:0:0:0:0/8",
&rr_dict, "net-dns.org", 3600)))
FAIL_r("getdns_str2rr_dict");
if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rdata_raw")))
FAIL_r("getdns_dict_remove_name");
print_dict(rr_dict);
/* Convert repeat block from rr_dict back to string.
*/
if ((r = getdns_rr_dict2str(rr_dict, &str)))
FAIL_r("getdns_rr_dict2str");
printf("%s", str);
free(str);
getdns_dict_destroy(rr_dict);
/* Parse over wire data, convert to string via dict, and print */
end_of_wire = wire;
wire = wire_buf;

View File

@ -1,5 +1,5 @@
{
"class": GETDNS_RRCLASS_CH,
"class": GETDNS_RRCLASS_IN,
"name": <bindata of "some.domain.tld.">,
"rdata":
{
@ -8,38 +8,95 @@
[
<bindata of "first string">,
<bindata of "second">,
<bindata of "and third">
<bindata of "and third">,
<bindata of "last string">
]
},
"ttl": 60,
"type": GETDNS_RRTYPE_TXT
}
0000 04 73 6f 6d 65 06 64 6f 6d 61 69 6e 03 74 6c 64 .some.do main.tld
0010 00 00 10 00 03 00 00 00 3c 00 1e 0c 66 69 72 73 ........ <...firs
0010 00 00 10 00 01 00 00 00 3c 00 1e 0c 66 69 72 73 ........ <...firs
0020 74 20 73 74 72 69 6e 67 06 73 65 63 6f 6e 64 09 t string .second.
0030 61 6e 64 20 74 68 69 72 64 and thir d.......
{
"class": GETDNS_RRCLASS_CH,
"name": <bindata of "some.domain.tld.">,
"rdata":
{
"txt_strings":
[
<bindata of "first string">,
<bindata of "second">,
<bindata of "and third">
]
},
"ttl": 60,
"type": GETDNS_RRTYPE_TXT
}
removed "/rdata/rdata_raw":
0000 04 73 6f 6d 65 06 64 6f 6d 61 69 6e 03 74 6c 64 .some.do main.tld
0010 00 00 10 00 03 00 00 00 3c 00 1e 0c 66 69 72 73 ........ <...firs
0010 00 00 10 00 01 00 00 00 3c 00 2a 0c 66 69 72 73 ........ <.*.firs
0020 74 20 73 74 72 69 6e 67 06 73 65 63 6f 6e 64 09 t string .second.
0030 61 6e 64 20 74 68 69 72 64 and thir d.......
0030 61 6e 64 20 74 68 69 72 64 0b 6c 61 73 74 20 73 and thir d.last s
0040 74 72 69 6e 67 tring... ........
some.domain.tld. 60 IN TXT "first string" "last string"
some.domain.tld. 60 IN TXT \# 0
www.getdnsapi.net. 0 IN A 185.49.141.37
0000 03 77 77 77 09 67 65 74 64 6e 73 61 70 69 03 6e .www.get dnsapi.n
0010 65 74 00 00 01 00 01 00 00 00 00 00 04 b9 31 8d et...... ......1.
0020 25 %....... ........
{
"class": GETDNS_RRCLASS_IN,
"name": <bindata of "hip2.nlnetlabs.nl.">,
"rdata":
{
"hit": <bindata of 0x200100107b1a74df365639cc39f1d578>,
"pk_algorithm": 2,
"public_key": <bindata of 0x03010001b771ca136e4aeb5ce44333c5...>,
"rendezvous_servers":
[
<bindata of "rvs1.example.com.">,
<bindata of "rvs2.example.com.">
]
},
"ttl": 3600,
"type": GETDNS_RRTYPE_HIP
}
hip2.nlnetlabs.nl. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs1.example.com. rvs2.example.com.
hip0.nlnetlabs.nl. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
{
"class": GETDNS_RRCLASS_IN,
"name": <bindata of "apl.net-dns.org.">,
"rdata":
{
"apitems":
[
{
"address_family": 1,
"afdpart": <bindata of 0xc0a82a>,
"n": 0,
"prefix": 26
},
{
"address_family": 1,
"afdpart": <bindata of 0xc0a82a40>,
"n": 0,
"prefix": 26
},
{
"address_family": 1,
"afdpart": <bindata of 0xc0a82a80>,
"n": 1,
"prefix": 25
},
{
"address_family": 1,
"afdpart": <bindata of 0xe0>,
"n": 0,
"prefix": 4
},
{
"address_family": 2,
"afdpart": <bindata of 0xff>,
"n": 0,
"prefix": 8
}
]
},
"ttl": 3600,
"type": GETDNS_RRTYPE_APL
}
apl.net-dns.org. 3600 IN APL 1:192.168.42.0/26 1:192.168.42.64/26 !1:192.168.42.128/25 1:224.0.0.0/4 2:ff00:0000:0000:0000:0000:0000:0000:0000/8