txt: introduce `ares_parse_txt_reply_ext`
Introduce `ares_txt_ext` structure with an extra `record_start` field, which indicates a start of a new TXT record, thus allowing to differentiate the chunks in the same record, from a chunks in a different record. Introduce a new API method: `ares_parse_txt_reply_ext` that works with this kind of struct.
This commit is contained in:
parent
0c4c1ca9bc
commit
53c2186e18
15
ares.h
15
ares.h
|
@ -484,6 +484,17 @@ struct ares_txt_reply {
|
||||||
size_t length; /* length excludes null termination */
|
size_t length; /* length excludes null termination */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* NOTE: This structure is a superset of ares_txt_reply
|
||||||
|
*/
|
||||||
|
struct ares_txt_ext {
|
||||||
|
struct ares_txt_ext *next;
|
||||||
|
unsigned char *txt;
|
||||||
|
size_t length;
|
||||||
|
/* 1 - if start of new record
|
||||||
|
* 0 - if a chunk in the same record */
|
||||||
|
unsigned char record_start;
|
||||||
|
};
|
||||||
|
|
||||||
struct ares_naptr_reply {
|
struct ares_naptr_reply {
|
||||||
struct ares_naptr_reply *next;
|
struct ares_naptr_reply *next;
|
||||||
unsigned char *flags;
|
unsigned char *flags;
|
||||||
|
@ -547,6 +558,10 @@ CARES_EXTERN int ares_parse_txt_reply(const unsigned char* abuf,
|
||||||
int alen,
|
int alen,
|
||||||
struct ares_txt_reply** txt_out);
|
struct ares_txt_reply** txt_out);
|
||||||
|
|
||||||
|
CARES_EXTERN int ares_parse_txt_reply_ext(const unsigned char* abuf,
|
||||||
|
int alen,
|
||||||
|
struct ares_txt_ext** txt_out);
|
||||||
|
|
||||||
CARES_EXTERN int ares_parse_naptr_reply(const unsigned char* abuf,
|
CARES_EXTERN int ares_parse_naptr_reply(const unsigned char* abuf,
|
||||||
int alen,
|
int alen,
|
||||||
struct ares_naptr_reply** naptr_out);
|
struct ares_naptr_reply** naptr_out);
|
||||||
|
|
|
@ -79,6 +79,7 @@ void ares_free_data(void *dataptr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARES_DATATYPE_TXT_REPLY:
|
case ARES_DATATYPE_TXT_REPLY:
|
||||||
|
case ARES_DATATYPE_TXT_EXT:
|
||||||
|
|
||||||
if (ptr->data.txt_reply.next)
|
if (ptr->data.txt_reply.next)
|
||||||
ares_free_data(ptr->data.txt_reply.next);
|
ares_free_data(ptr->data.txt_reply.next);
|
||||||
|
@ -162,6 +163,10 @@ void *ares_malloc_data(ares_datatype type)
|
||||||
ptr->data.srv_reply.port = 0;
|
ptr->data.srv_reply.port = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ARES_DATATYPE_TXT_EXT:
|
||||||
|
ptr->data.txt_ext.record_start = 0;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
case ARES_DATATYPE_TXT_REPLY:
|
case ARES_DATATYPE_TXT_REPLY:
|
||||||
ptr->data.txt_reply.next = NULL;
|
ptr->data.txt_reply.next = NULL;
|
||||||
ptr->data.txt_reply.txt = NULL;
|
ptr->data.txt_reply.txt = NULL;
|
||||||
|
|
14
ares_data.h
14
ares_data.h
|
@ -18,6 +18,7 @@ typedef enum {
|
||||||
ARES_DATATYPE_UNKNOWN = 1, /* unknown data type - introduced in 1.7.0 */
|
ARES_DATATYPE_UNKNOWN = 1, /* unknown data type - introduced in 1.7.0 */
|
||||||
ARES_DATATYPE_SRV_REPLY, /* struct ares_srv_reply - introduced in 1.7.0 */
|
ARES_DATATYPE_SRV_REPLY, /* struct ares_srv_reply - introduced in 1.7.0 */
|
||||||
ARES_DATATYPE_TXT_REPLY, /* struct ares_txt_reply - introduced in 1.7.0 */
|
ARES_DATATYPE_TXT_REPLY, /* struct ares_txt_reply - introduced in 1.7.0 */
|
||||||
|
ARES_DATATYPE_TXT_EXT, /* struct ares_txt_ext - introduced in 1.11.0 */
|
||||||
ARES_DATATYPE_ADDR_NODE, /* struct ares_addr_node - introduced in 1.7.1 */
|
ARES_DATATYPE_ADDR_NODE, /* struct ares_addr_node - introduced in 1.7.1 */
|
||||||
ARES_DATATYPE_MX_REPLY, /* struct ares_mx_reply - introduced in 1.7.2 */
|
ARES_DATATYPE_MX_REPLY, /* struct ares_mx_reply - introduced in 1.7.2 */
|
||||||
ARES_DATATYPE_NAPTR_REPLY,/* struct ares_naptr_reply - introduced in 1.7.6 */
|
ARES_DATATYPE_NAPTR_REPLY,/* struct ares_naptr_reply - introduced in 1.7.6 */
|
||||||
|
@ -56,13 +57,14 @@ struct ares_data {
|
||||||
ares_datatype type; /* Actual data type identifier. */
|
ares_datatype type; /* Actual data type identifier. */
|
||||||
unsigned int mark; /* Private ares_data signature. */
|
unsigned int mark; /* Private ares_data signature. */
|
||||||
union {
|
union {
|
||||||
struct ares_txt_reply txt_reply;
|
struct ares_txt_reply txt_reply;
|
||||||
struct ares_srv_reply srv_reply;
|
struct ares_txt_ext txt_ext;
|
||||||
struct ares_addr_node addr_node;
|
struct ares_srv_reply srv_reply;
|
||||||
|
struct ares_addr_node addr_node;
|
||||||
struct ares_addr_port_node addr_port_node;
|
struct ares_addr_port_node addr_port_node;
|
||||||
struct ares_mx_reply mx_reply;
|
struct ares_mx_reply mx_reply;
|
||||||
struct ares_naptr_reply naptr_reply;
|
struct ares_naptr_reply naptr_reply;
|
||||||
struct ares_soa_reply soa_reply;
|
struct ares_soa_reply soa_reply;
|
||||||
} data;
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,13 +22,16 @@ ares_parse_txt_reply \- Parse a reply to a DNS query of type TXT
|
||||||
.PP
|
.PP
|
||||||
.B int ares_parse_txt_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
|
.B int ares_parse_txt_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
|
||||||
.B struct ares_txt_reply **\fItxt_out\fP);
|
.B struct ares_txt_reply **\fItxt_out\fP);
|
||||||
|
.PP
|
||||||
|
.B int ares_parse_txt_reply_ext(const unsigned char* \fIabuf\fP, int \fIalen\fP,
|
||||||
|
.B struct ares_txt_ext **\fItxt_out\fP);
|
||||||
.fi
|
.fi
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
The
|
The
|
||||||
.B ares_parse_txt_reply
|
.BR "ares_parse_txt_reply" " (" "ares_parse_txt_reply_ext" ")"
|
||||||
function parses the response to a query of type TXT into a
|
function parses the response to a query of type TXT into a
|
||||||
linked list (one element per sub-string) of
|
linked list (one element per sub-string) of
|
||||||
.I struct ares_txt_reply
|
.IR "struct ares_txt_reply" " (" "struct ares_txt_ext" ")"
|
||||||
The parameters
|
The parameters
|
||||||
.I abuf
|
.I abuf
|
||||||
and
|
and
|
||||||
|
@ -55,8 +58,44 @@ struct ares_txt_reply {
|
||||||
.fi
|
.fi
|
||||||
.in
|
.in
|
||||||
.PP
|
.PP
|
||||||
|
The structure
|
||||||
|
.I ares_txt_ext
|
||||||
|
contains the following fields:
|
||||||
|
.sp
|
||||||
|
.in +4n
|
||||||
|
.nf
|
||||||
|
struct ares_txt_ext {
|
||||||
|
struct ares_txt_ext *next;
|
||||||
|
unsigned int length;
|
||||||
|
unsigned char *txt;
|
||||||
|
unsigned char record_start;
|
||||||
|
};
|
||||||
|
.fi
|
||||||
|
.in
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.I record_start
|
||||||
|
field in
|
||||||
|
.I struct ares_txt_ext
|
||||||
|
is 1 if this structure is a start of a TXT record, and 0 if the structure is a
|
||||||
|
continuation of a previous record. The linked list of the
|
||||||
|
.I struct ares_txt_ext
|
||||||
|
will have at least one item with
|
||||||
|
.I record_start
|
||||||
|
equal to 1, and may have some items with
|
||||||
|
.I record_start
|
||||||
|
equal to 0 between them.
|
||||||
|
.PP
|
||||||
|
These sequences of
|
||||||
|
.I struct ares_txt_ext
|
||||||
|
(starting from the item with
|
||||||
|
.I record_start
|
||||||
|
equal to 1, and ending right before the record start item) may be treated as
|
||||||
|
either components of a single TXT record or as a multi-parted TXT record,
|
||||||
|
depending on particular use case.
|
||||||
|
.PP
|
||||||
.SH RETURN VALUES
|
.SH RETURN VALUES
|
||||||
.B ares_parse_txt_reply
|
.BR "ares_parse_txt_reply" " (" "ares_parse_txt_reply_ext" ")"
|
||||||
can return any of the following values:
|
can return any of the following values:
|
||||||
.TP 15
|
.TP 15
|
||||||
.B ARES_SUCCESS
|
.B ARES_SUCCESS
|
||||||
|
@ -77,4 +116,5 @@ This function was first introduced in c-ares version 1.7.0.
|
||||||
.BR ares_free_data (3)
|
.BR ares_free_data (3)
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
Written by Jakub Hrozek <jhrozek@redhat.com>, on behalf of Red Hat, Inc http://www.redhat.com
|
Written by Jakub Hrozek <jhrozek@redhat.com>, on behalf of Red Hat, Inc http://www.redhat.com
|
||||||
|
.PP
|
||||||
|
Amended by Fedor Indutny <fedor@indutny.com>, on behalf of PayPal, Inc https://www.paypal.com
|
||||||
|
|
|
@ -44,9 +44,9 @@
|
||||||
#include "ares_data.h"
|
#include "ares_data.h"
|
||||||
#include "ares_private.h"
|
#include "ares_private.h"
|
||||||
|
|
||||||
int
|
static int
|
||||||
ares_parse_txt_reply (const unsigned char *abuf, int alen,
|
ares__parse_txt_reply (const unsigned char *abuf, int alen,
|
||||||
struct ares_txt_reply **txt_out)
|
int ex, void **txt_out)
|
||||||
{
|
{
|
||||||
size_t substr_len;
|
size_t substr_len;
|
||||||
unsigned int qdcount, ancount, i;
|
unsigned int qdcount, ancount, i;
|
||||||
|
@ -55,9 +55,9 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen,
|
||||||
int status, rr_type, rr_class, rr_len;
|
int status, rr_type, rr_class, rr_len;
|
||||||
long len;
|
long len;
|
||||||
char *hostname = NULL, *rr_name = NULL;
|
char *hostname = NULL, *rr_name = NULL;
|
||||||
struct ares_txt_reply *txt_head = NULL;
|
struct ares_txt_ext *txt_head = NULL;
|
||||||
struct ares_txt_reply *txt_last = NULL;
|
struct ares_txt_ext *txt_last = NULL;
|
||||||
struct ares_txt_reply *txt_curr;
|
struct ares_txt_ext *txt_curr;
|
||||||
|
|
||||||
/* Set *txt_out to NULL for all failure cases. */
|
/* Set *txt_out to NULL for all failure cases. */
|
||||||
*txt_out = NULL;
|
*txt_out = NULL;
|
||||||
|
@ -133,10 +133,9 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
++strptr;
|
|
||||||
|
|
||||||
/* Allocate storage for this TXT answer appending it to the list */
|
/* Allocate storage for this TXT answer appending it to the list */
|
||||||
txt_curr = ares_malloc_data(ARES_DATATYPE_TXT_REPLY);
|
txt_curr = ares_malloc_data(ex ? ARES_DATATYPE_TXT_EXT :
|
||||||
|
ARES_DATATYPE_TXT_REPLY);
|
||||||
if (!txt_curr)
|
if (!txt_curr)
|
||||||
{
|
{
|
||||||
status = ARES_ENOMEM;
|
status = ARES_ENOMEM;
|
||||||
|
@ -152,6 +151,8 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen,
|
||||||
}
|
}
|
||||||
txt_last = txt_curr;
|
txt_last = txt_curr;
|
||||||
|
|
||||||
|
if (ex)
|
||||||
|
txt_curr->record_start = (strptr == aptr);
|
||||||
txt_curr->length = substr_len;
|
txt_curr->length = substr_len;
|
||||||
txt_curr->txt = ares_malloc (substr_len + 1/* Including null byte */);
|
txt_curr->txt = ares_malloc (substr_len + 1/* Including null byte */);
|
||||||
if (txt_curr->txt == NULL)
|
if (txt_curr->txt == NULL)
|
||||||
|
@ -159,6 +160,8 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen,
|
||||||
status = ARES_ENOMEM;
|
status = ARES_ENOMEM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++strptr;
|
||||||
memcpy ((char *) txt_curr->txt, strptr, substr_len);
|
memcpy ((char *) txt_curr->txt, strptr, substr_len);
|
||||||
|
|
||||||
/* Make sure we NULL-terminate */
|
/* Make sure we NULL-terminate */
|
||||||
|
@ -200,3 +203,18 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen,
|
||||||
|
|
||||||
return ARES_SUCCESS;
|
return ARES_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ares_parse_txt_reply (const unsigned char *abuf, int alen,
|
||||||
|
struct ares_txt_reply **txt_out)
|
||||||
|
{
|
||||||
|
return ares__parse_txt_reply(abuf, alen, 0, (void **) txt_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
ares_parse_txt_reply_ext (const unsigned char *abuf, int alen,
|
||||||
|
struct ares_txt_ext **txt_out)
|
||||||
|
{
|
||||||
|
return ares__parse_txt_reply(abuf, alen, 1, (void **) txt_out);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue