DNS Write: fix name compression

pull/600/head
Brad House 1 year ago
parent 80d940cd3d
commit 5bbf3f3962
  1. 72
      src/lib/ares__buf.c
  2. 10
      src/lib/ares__buf.h
  3. 10
      src/lib/ares_dns_name.c
  4. 6
      test/ares-test-internal.cc

@ -832,3 +832,75 @@ ares_status_t ares__buf_parse_dns_str(ares__buf_t *buf, size_t remaining_len,
return ares__buf_parse_dns_binstr(buf, remaining_len, (unsigned char **)str,
&len, allow_multiple);
}
static ares_status_t ares__buf_append_num_hex(ares__buf_t *buf, size_t num,
size_t len)
{
size_t i;
static const unsigned char hexbytes[] = "0123456789ABCDEF";
for (i=len; i>0; i--) {
ares_status_t status;
status = ares__buf_append_byte(buf, hexbytes[(num >> ((i-1) * 4)) & 0xF]);
if (status != ARES_SUCCESS)
return status;
}
return ARES_SUCCESS;
}
static ares_status_t ares__buf_append_str(ares__buf_t *buf, const char *str)
{
return ares__buf_append(buf, (const unsigned char *)str, ares_strlen(str));
}
ares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data,
size_t len)
{
size_t i;
ares_status_t status;
/* Each line is 16 bytes */
for (i=0; i<len; i += 16) {
size_t j;
/* Address */
status = ares__buf_append_num_hex(buf, i, 6);
if (status != ARES_SUCCESS)
return status;
/* | */
status = ares__buf_append_str(buf, " | ");
if (status != ARES_SUCCESS)
return status;
for (j=i; j<i+16; j++) {
if (j >= len) {
status = ares__buf_append_str(buf, " ");
} else {
status = ares__buf_append_num_hex(buf, data[j], 2);
}
if (status != ARES_SUCCESS)
return status;
status = ares__buf_append_byte(buf, ' ');
if (status != ARES_SUCCESS)
return status;
}
/* | */
status = ares__buf_append_str(buf, " | ");
if (status != ARES_SUCCESS)
return status;
for (j=i; j<i+16; j++) {
if (j >= len) {
break;
}
status = ares__buf_append_byte(buf, ares__isprint(data[j])?data[j]:'.');
if (status != ARES_SUCCESS)
return status;
}
ares__buf_append_byte(buf, '\n');
}
return status;
}

@ -145,6 +145,16 @@ unsigned char *ares__buf_append_start(ares__buf_t *buf, size_t *len);
*/
void ares__buf_append_finish(ares__buf_t *buf, size_t len);
/*! Write the data provided to the buffer in a hexdump format.
*
* \param[in] buf Initialized buffer object.
* \param[in] data Data to hex dump
* \param[in] data_len Length of data to hexdump
* \return ARES_SUCCESS on success.
*/
ares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data,
size_t len);
/*! Clean up ares__buf_t and return allocated pointer to unprocessed data. It
* is the responsibility of the caller to ares_free() the returned buffer.
* The passed in buf parameter is invalidated by this call.

@ -76,7 +76,7 @@ static ares_status_t ares__nameoffset_create(ares__llist_t **list,
goto fail;
}
status = ARES_SUCCESS;
return ARES_SUCCESS;
fail:
ares__nameoffset_free(off);
@ -361,7 +361,7 @@ ares_status_t ares__dns_name_write(ares__buf_t *buf, ares__llist_t **list,
{
const ares_nameoffset_t *off = NULL;
size_t name_len;
size_t pos = ares__buf_get_position(buf);
size_t pos = ares__buf_len(buf);
ares_dns_labels_t labels;
char name_copy[512];
ares_status_t status;
@ -381,8 +381,8 @@ ares_status_t ares__dns_name_write(ares__buf_t *buf, ares__llist_t **list,
off = ares__nameoffset_find(*list, name_copy);
if (off != NULL && off->name_len != name_len) {
/* truncate */
name_len -= (off->name_len + 1);
name_copy[name_len - 1] = 0;
name_len -= (off->name_len + 1);
name_copy[name_len] = 0;
}
}
@ -431,7 +431,7 @@ ares_status_t ares__dns_name_write(ares__buf_t *buf, ares__llist_t **list,
/* Store pointer for future jumps as long as its not an exact match for
* a prior entry */
if (list != NULL && off != NULL && off->name_len != name_len &&
if (list != NULL && (off == NULL || off->name_len != name_len) &&
name_len > 0) {
status = ares__nameoffset_create(list, name /* not truncated copy! */, pos);
if (status != ARES_SUCCESS) {

@ -470,7 +470,6 @@ TEST_F(LibraryTest, DNSRecord) {
struct ares_in6_addr addr6;
unsigned char *msg = NULL;
size_t msglen = 0;
size_t qdcount = 0;
size_t ancount = 0;
size_t nscount = 0;
@ -651,6 +650,11 @@ TEST_F(LibraryTest, DNSRecord) {
/* Write */
EXPECT_EQ(ARES_SUCCESS, ares_dns_write(dnsrec, &msg, &msglen));
ares__buf_t *hexdump = ares__buf_create();
EXPECT_EQ(ARES_SUCCESS, ares__buf_hexdump(hexdump, msg, msglen));
char *hexdata = ares__buf_finish_str(hexdump, NULL);
//printf("HEXDUMP\n%s", hexdata);
ares_dns_record_destroy(dnsrec); dnsrec = NULL;
/* Parse */

Loading…
Cancel
Save