986ba33c7a
I've been holding back on this because 1.7.0 requires OpenSSL 1.1.0 or newer for full DANE support. But we can't wait forever, and nothing in base uses DANE anyway, so here we go.
758 lines
16 KiB
C
758 lines
16 KiB
C
/*
|
|
* rdata.c
|
|
*
|
|
* rdata implementation
|
|
*
|
|
* a Net::DNS like library for C
|
|
*
|
|
* (c) NLnet Labs, 2004-2006
|
|
*
|
|
* See the file LICENSE for the license
|
|
*/
|
|
|
|
#include <ldns/config.h>
|
|
|
|
#include <ldns/ldns.h>
|
|
|
|
/*
|
|
* Access functions
|
|
* do this as functions to get type checking
|
|
*/
|
|
|
|
/* read */
|
|
size_t
|
|
ldns_rdf_size(const ldns_rdf *rd)
|
|
{
|
|
assert(rd != NULL);
|
|
return rd->_size;
|
|
}
|
|
|
|
ldns_rdf_type
|
|
ldns_rdf_get_type(const ldns_rdf *rd)
|
|
{
|
|
assert(rd != NULL);
|
|
return rd->_type;
|
|
}
|
|
|
|
uint8_t *
|
|
ldns_rdf_data(const ldns_rdf *rd)
|
|
{
|
|
assert(rd != NULL);
|
|
return rd->_data;
|
|
}
|
|
|
|
/* write */
|
|
void
|
|
ldns_rdf_set_size(ldns_rdf *rd, size_t size)
|
|
{
|
|
assert(rd != NULL);
|
|
rd->_size = size;
|
|
}
|
|
|
|
void
|
|
ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type)
|
|
{
|
|
assert(rd != NULL);
|
|
rd->_type = type;
|
|
}
|
|
|
|
void
|
|
ldns_rdf_set_data(ldns_rdf *rd, void *data)
|
|
{
|
|
/* only copy the pointer */
|
|
assert(rd != NULL);
|
|
rd->_data = data;
|
|
}
|
|
|
|
/* for types that allow it, return
|
|
* the native/host order type */
|
|
uint8_t
|
|
ldns_rdf2native_int8(const ldns_rdf *rd)
|
|
{
|
|
uint8_t data;
|
|
|
|
/* only allow 8 bit rdfs */
|
|
if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_BYTE) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&data, ldns_rdf_data(rd), sizeof(data));
|
|
return data;
|
|
}
|
|
|
|
uint16_t
|
|
ldns_rdf2native_int16(const ldns_rdf *rd)
|
|
{
|
|
uint16_t data;
|
|
|
|
/* only allow 16 bit rdfs */
|
|
if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_WORD) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&data, ldns_rdf_data(rd), sizeof(data));
|
|
return ntohs(data);
|
|
}
|
|
|
|
uint32_t
|
|
ldns_rdf2native_int32(const ldns_rdf *rd)
|
|
{
|
|
uint32_t data;
|
|
|
|
/* only allow 32 bit rdfs */
|
|
if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&data, ldns_rdf_data(rd), sizeof(data));
|
|
return ntohl(data);
|
|
}
|
|
|
|
time_t
|
|
ldns_rdf2native_time_t(const ldns_rdf *rd)
|
|
{
|
|
uint32_t data;
|
|
|
|
/* only allow 32 bit rdfs */
|
|
if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD ||
|
|
ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_TIME) {
|
|
return 0;
|
|
}
|
|
memcpy(&data, ldns_rdf_data(rd), sizeof(data));
|
|
return (time_t)ntohl(data);
|
|
}
|
|
|
|
ldns_rdf *
|
|
ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value)
|
|
{
|
|
return ldns_rdf_new_frm_data(type, LDNS_RDF_SIZE_BYTE, &value);
|
|
}
|
|
|
|
ldns_rdf *
|
|
ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value)
|
|
{
|
|
uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1);
|
|
ldns_rdf* rdf;
|
|
if (!rdf_data) {
|
|
return NULL;
|
|
}
|
|
ldns_write_uint16(rdf_data, value);
|
|
rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data);
|
|
if(!rdf)
|
|
LDNS_FREE(rdf_data);
|
|
return rdf;
|
|
}
|
|
|
|
ldns_rdf *
|
|
ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value)
|
|
{
|
|
uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1);
|
|
ldns_rdf* rdf;
|
|
if (!rdf_data) {
|
|
return NULL;
|
|
}
|
|
ldns_write_uint32(rdf_data, value);
|
|
rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data);
|
|
if(!rdf)
|
|
LDNS_FREE(rdf_data);
|
|
return rdf;
|
|
}
|
|
|
|
ldns_rdf *
|
|
ldns_native2rdf_int16_data(size_t size, uint8_t *data)
|
|
{
|
|
uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2);
|
|
ldns_rdf* rdf;
|
|
if (!rdf_data) {
|
|
return NULL;
|
|
}
|
|
ldns_write_uint16(rdf_data, size);
|
|
memcpy(rdf_data + 2, data, size);
|
|
rdf = ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data);
|
|
if(!rdf)
|
|
LDNS_FREE(rdf_data);
|
|
return rdf;
|
|
}
|
|
|
|
/* note: data must be allocated memory */
|
|
ldns_rdf *
|
|
ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
|
|
{
|
|
ldns_rdf *rd;
|
|
rd = LDNS_MALLOC(ldns_rdf);
|
|
if (!rd) {
|
|
return NULL;
|
|
}
|
|
ldns_rdf_set_size(rd, size);
|
|
ldns_rdf_set_type(rd, type);
|
|
ldns_rdf_set_data(rd, data);
|
|
return rd;
|
|
}
|
|
|
|
ldns_rdf *
|
|
ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
|
|
{
|
|
ldns_rdf *rdf;
|
|
|
|
/* if the size is too big, fail */
|
|
if (size > LDNS_MAX_RDFLEN) {
|
|
return NULL;
|
|
}
|
|
|
|
/* allocate space */
|
|
rdf = LDNS_MALLOC(ldns_rdf);
|
|
if (!rdf) {
|
|
return NULL;
|
|
}
|
|
rdf->_data = LDNS_XMALLOC(uint8_t, size);
|
|
if (!rdf->_data) {
|
|
LDNS_FREE(rdf);
|
|
return NULL;
|
|
}
|
|
|
|
/* set the values */
|
|
ldns_rdf_set_type(rdf, type);
|
|
ldns_rdf_set_size(rdf, size);
|
|
memcpy(rdf->_data, data, size);
|
|
|
|
return rdf;
|
|
}
|
|
|
|
ldns_rdf *
|
|
ldns_rdf_clone(const ldns_rdf *rd)
|
|
{
|
|
assert(rd != NULL);
|
|
return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd),
|
|
ldns_rdf_size(rd), ldns_rdf_data(rd)));
|
|
}
|
|
|
|
void
|
|
ldns_rdf_deep_free(ldns_rdf *rd)
|
|
{
|
|
if (rd) {
|
|
if (rd->_data) {
|
|
LDNS_FREE(rd->_data);
|
|
}
|
|
LDNS_FREE(rd);
|
|
}
|
|
}
|
|
|
|
void
|
|
ldns_rdf_free(ldns_rdf *rd)
|
|
{
|
|
if (rd) {
|
|
LDNS_FREE(rd);
|
|
}
|
|
}
|
|
|
|
ldns_rdf *
|
|
ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
|
|
{
|
|
ldns_rdf *rdf = NULL;
|
|
ldns_status status;
|
|
|
|
switch (type) {
|
|
case LDNS_RDF_TYPE_DNAME:
|
|
status = ldns_str2rdf_dname(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_INT8:
|
|
status = ldns_str2rdf_int8(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_INT16:
|
|
status = ldns_str2rdf_int16(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_INT32:
|
|
status = ldns_str2rdf_int32(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_A:
|
|
status = ldns_str2rdf_a(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_AAAA:
|
|
status = ldns_str2rdf_aaaa(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_STR:
|
|
status = ldns_str2rdf_str(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_APL:
|
|
status = ldns_str2rdf_apl(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_B64:
|
|
status = ldns_str2rdf_b64(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_B32_EXT:
|
|
status = ldns_str2rdf_b32_ext(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_HEX:
|
|
status = ldns_str2rdf_hex(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_NSEC:
|
|
status = ldns_str2rdf_nsec(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_TYPE:
|
|
status = ldns_str2rdf_type(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_CLASS:
|
|
status = ldns_str2rdf_class(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_CERT_ALG:
|
|
status = ldns_str2rdf_cert_alg(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_ALG:
|
|
status = ldns_str2rdf_alg(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_UNKNOWN:
|
|
status = ldns_str2rdf_unknown(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_TIME:
|
|
status = ldns_str2rdf_time(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_PERIOD:
|
|
status = ldns_str2rdf_period(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_HIP:
|
|
status = ldns_str2rdf_hip(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_SERVICE:
|
|
status = ldns_str2rdf_service(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_LOC:
|
|
status = ldns_str2rdf_loc(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_WKS:
|
|
status = ldns_str2rdf_wks(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_NSAP:
|
|
status = ldns_str2rdf_nsap(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_ATMA:
|
|
status = ldns_str2rdf_atma(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_IPSECKEY:
|
|
status = ldns_str2rdf_ipseckey(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_NSEC3_SALT:
|
|
status = ldns_str2rdf_nsec3_salt(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
|
|
status = ldns_str2rdf_b32_ext(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_ILNP64:
|
|
status = ldns_str2rdf_ilnp64(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_EUI48:
|
|
status = ldns_str2rdf_eui48(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_EUI64:
|
|
status = ldns_str2rdf_eui64(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_TAG:
|
|
status = ldns_str2rdf_tag(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_LONG_STR:
|
|
status = ldns_str2rdf_long_str(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
|
|
status = ldns_str2rdf_certificate_usage(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_SELECTOR:
|
|
status = ldns_str2rdf_selector(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_MATCHING_TYPE:
|
|
status = ldns_str2rdf_matching_type(&rdf, str);
|
|
break;
|
|
case LDNS_RDF_TYPE_NONE:
|
|
default:
|
|
/* default default ??? */
|
|
status = LDNS_STATUS_ERR;
|
|
break;
|
|
}
|
|
if (LDNS_STATUS_OK == status) {
|
|
ldns_rdf_set_type(rdf, type);
|
|
return rdf;
|
|
}
|
|
if (rdf) {
|
|
LDNS_FREE(rdf);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
ldns_status
|
|
ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp)
|
|
{
|
|
return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL);
|
|
}
|
|
|
|
ldns_status
|
|
ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
|
|
{
|
|
char *line;
|
|
ldns_rdf *r;
|
|
ssize_t t;
|
|
|
|
line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
|
|
if (!line) {
|
|
return LDNS_STATUS_MEM_ERR;
|
|
}
|
|
|
|
/* read an entire line in from the file */
|
|
if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) {
|
|
LDNS_FREE(line);
|
|
return LDNS_STATUS_SYNTAX_RDATA_ERR;
|
|
}
|
|
r = ldns_rdf_new_frm_str(type, (const char*) line);
|
|
LDNS_FREE(line);
|
|
if (rdf) {
|
|
*rdf = r;
|
|
return LDNS_STATUS_OK;
|
|
} else {
|
|
return LDNS_STATUS_NULL;
|
|
}
|
|
}
|
|
|
|
ldns_rdf *
|
|
ldns_rdf_address_reverse(const ldns_rdf *rd)
|
|
{
|
|
uint8_t buf_4[LDNS_IP4ADDRLEN];
|
|
uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
|
|
ldns_rdf *rev;
|
|
ldns_rdf *in_addr;
|
|
ldns_rdf *ret_dname;
|
|
uint8_t octet;
|
|
uint8_t nnibble;
|
|
uint8_t nibble;
|
|
uint8_t i, j;
|
|
|
|
char *char_dname;
|
|
int nbit;
|
|
|
|
if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
|
|
ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) {
|
|
return NULL;
|
|
}
|
|
|
|
in_addr = NULL;
|
|
ret_dname = NULL;
|
|
|
|
switch(ldns_rdf_get_type(rd)) {
|
|
case LDNS_RDF_TYPE_A:
|
|
/* the length of the buffer is 4 */
|
|
buf_4[3] = ldns_rdf_data(rd)[0];
|
|
buf_4[2] = ldns_rdf_data(rd)[1];
|
|
buf_4[1] = ldns_rdf_data(rd)[2];
|
|
buf_4[0] = ldns_rdf_data(rd)[3];
|
|
in_addr = ldns_dname_new_frm_str("in-addr.arpa.");
|
|
if (!in_addr) {
|
|
return NULL;
|
|
}
|
|
/* make a new rdf and convert that back */
|
|
rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A,
|
|
LDNS_IP4ADDRLEN, (void*)&buf_4);
|
|
if (!rev) {
|
|
LDNS_FREE(in_addr);
|
|
return NULL;
|
|
}
|
|
|
|
/* convert rev to a string */
|
|
char_dname = ldns_rdf2str(rev);
|
|
if (!char_dname) {
|
|
LDNS_FREE(in_addr);
|
|
ldns_rdf_deep_free(rev);
|
|
return NULL;
|
|
}
|
|
/* transform back to rdf with type dname */
|
|
ret_dname = ldns_dname_new_frm_str(char_dname);
|
|
if (!ret_dname) {
|
|
LDNS_FREE(in_addr);
|
|
ldns_rdf_deep_free(rev);
|
|
LDNS_FREE(char_dname);
|
|
return NULL;
|
|
}
|
|
/* not needed anymore */
|
|
ldns_rdf_deep_free(rev);
|
|
LDNS_FREE(char_dname);
|
|
break;
|
|
case LDNS_RDF_TYPE_AAAA:
|
|
/* some foo magic to reverse the nibbles ... */
|
|
|
|
for (nbit = 127; nbit >= 0; nbit = nbit - 4) {
|
|
/* calculate octet (8 bit) */
|
|
octet = ( ((unsigned int) nbit) & 0x78) >> 3;
|
|
/* calculate nibble */
|
|
nnibble = ( ((unsigned int) nbit) & 0x04) >> 2;
|
|
/* extract nibble */
|
|
nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
|
|
nnibble)) ) ) >> ( 4 * (1 -
|
|
nnibble));
|
|
|
|
buf_6[(LDNS_IP6ADDRLEN * 2 - 1) -
|
|
(octet * 2 + nnibble)] =
|
|
(uint8_t)ldns_int_to_hexdigit((int)nibble);
|
|
}
|
|
|
|
char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4));
|
|
if (!char_dname) {
|
|
return NULL;
|
|
}
|
|
char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */
|
|
|
|
/* walk the string and add . 's */
|
|
for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) {
|
|
char_dname[j] = (char)buf_6[i];
|
|
if (i != LDNS_IP6ADDRLEN * 2 - 1) {
|
|
char_dname[j + 1] = '.';
|
|
}
|
|
}
|
|
in_addr = ldns_dname_new_frm_str("ip6.arpa.");
|
|
if (!in_addr) {
|
|
LDNS_FREE(char_dname);
|
|
return NULL;
|
|
}
|
|
|
|
/* convert rev to a string */
|
|
ret_dname = ldns_dname_new_frm_str(char_dname);
|
|
LDNS_FREE(char_dname);
|
|
if (!ret_dname) {
|
|
ldns_rdf_deep_free(in_addr);
|
|
return NULL;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
/* add the suffix */
|
|
rev = ldns_dname_cat_clone(ret_dname, in_addr);
|
|
|
|
ldns_rdf_deep_free(ret_dname);
|
|
ldns_rdf_deep_free(in_addr);
|
|
return rev;
|
|
}
|
|
|
|
ldns_status
|
|
ldns_rdf_hip_get_alg_hit_pk(ldns_rdf *rdf, uint8_t* alg,
|
|
uint8_t *hit_size, uint8_t** hit,
|
|
uint16_t *pk_size, uint8_t** pk)
|
|
{
|
|
uint8_t *data;
|
|
size_t rdf_size;
|
|
|
|
if (! rdf || ! alg || ! hit || ! hit_size || ! pk || ! pk_size) {
|
|
return LDNS_STATUS_INVALID_POINTER;
|
|
} else if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_HIP) {
|
|
return LDNS_STATUS_INVALID_RDF_TYPE;
|
|
} else if ((rdf_size = ldns_rdf_size(rdf)) < 6) {
|
|
return LDNS_STATUS_WIRE_RDATA_ERR;
|
|
}
|
|
data = ldns_rdf_data(rdf);
|
|
*hit_size = data[0];
|
|
*alg = data[1];
|
|
*pk_size = ldns_read_uint16(data + 2);
|
|
*hit = data + 4;
|
|
*pk = data + 4 + *hit_size;
|
|
if (*hit_size == 0 || *pk_size == 0 ||
|
|
rdf_size < (size_t) *hit_size + *pk_size + 4) {
|
|
return LDNS_STATUS_WIRE_RDATA_ERR;
|
|
}
|
|
return LDNS_STATUS_OK;
|
|
}
|
|
|
|
ldns_status
|
|
ldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf** rdf, uint8_t alg,
|
|
uint8_t hit_size, uint8_t *hit,
|
|
uint16_t pk_size, uint8_t *pk)
|
|
{
|
|
uint8_t *data;
|
|
|
|
if (! rdf) {
|
|
return LDNS_STATUS_INVALID_POINTER;
|
|
}
|
|
if (4 + hit_size + pk_size > LDNS_MAX_RDFLEN) {
|
|
return LDNS_STATUS_RDATA_OVERFLOW;
|
|
}
|
|
data = LDNS_XMALLOC(uint8_t, 4 + hit_size + pk_size);
|
|
if (data == NULL) {
|
|
return LDNS_STATUS_MEM_ERR;
|
|
}
|
|
data[0] = hit_size;
|
|
data[1] = alg;
|
|
ldns_write_uint16(data + 2, pk_size);
|
|
memcpy(data + 4, hit, hit_size);
|
|
memcpy(data + 4 + hit_size, pk, pk_size);
|
|
*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HIP, 4 + hit_size + pk_size, data);
|
|
if (! *rdf) {
|
|
LDNS_FREE(data);
|
|
return LDNS_STATUS_MEM_ERR;
|
|
}
|
|
return LDNS_STATUS_OK;
|
|
}
|
|
|
|
ldns_status
|
|
ldns_octet(char *word, size_t *length)
|
|
{
|
|
char *s;
|
|
char *p;
|
|
*length = 0;
|
|
|
|
for (s = p = word; *s != '\0'; s++,p++) {
|
|
switch (*s) {
|
|
case '.':
|
|
if (s[1] == '.') {
|
|
return LDNS_STATUS_EMPTY_LABEL;
|
|
}
|
|
*p = *s;
|
|
(*length)++;
|
|
break;
|
|
case '\\':
|
|
if ('0' <= s[1] && s[1] <= '9' &&
|
|
'0' <= s[2] && s[2] <= '9' &&
|
|
'0' <= s[3] && s[3] <= '9') {
|
|
/* \DDD seen */
|
|
int val = ((s[1] - '0') * 100 +
|
|
(s[2] - '0') * 10 + (s[3] - '0'));
|
|
|
|
if (0 <= val && val <= 255) {
|
|
/* this also handles \0 */
|
|
s += 3;
|
|
*p = val;
|
|
(*length)++;
|
|
} else {
|
|
return LDNS_STATUS_DDD_OVERFLOW;
|
|
}
|
|
} else {
|
|
/* an espaced character, like \<space> ?
|
|
* remove the '\' keep the rest */
|
|
*p = *++s;
|
|
(*length)++;
|
|
}
|
|
break;
|
|
case '\"':
|
|
/* non quoted " Is either first or the last character in
|
|
* the string */
|
|
|
|
*p = *++s; /* skip it */
|
|
(*length)++;
|
|
/* I'm not sure if this is needed in libdns... MG */
|
|
if ( *s == '\0' ) {
|
|
/* ok, it was the last one */
|
|
*p = '\0';
|
|
return LDNS_STATUS_OK;
|
|
}
|
|
break;
|
|
default:
|
|
*p = *s;
|
|
(*length)++;
|
|
break;
|
|
}
|
|
}
|
|
*p = '\0';
|
|
return LDNS_STATUS_OK;
|
|
}
|
|
|
|
int
|
|
ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
|
|
{
|
|
uint16_t i1, i2, i;
|
|
uint8_t *d1, *d2;
|
|
|
|
/* only when both are not NULL we can say anything about them */
|
|
if (!rd1 && !rd2) {
|
|
return 0;
|
|
}
|
|
if (!rd1 || !rd2) {
|
|
return -1;
|
|
}
|
|
i1 = ldns_rdf_size(rd1);
|
|
i2 = ldns_rdf_size(rd2);
|
|
|
|
if (i1 < i2) {
|
|
return -1;
|
|
} else if (i1 > i2) {
|
|
return +1;
|
|
} else {
|
|
d1 = (uint8_t*)ldns_rdf_data(rd1);
|
|
d2 = (uint8_t*)ldns_rdf_data(rd2);
|
|
for(i = 0; i < i1; i++) {
|
|
if (d1[i] < d2[i]) {
|
|
return -1;
|
|
} else if (d1[i] > d2[i]) {
|
|
return +1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint32_t
|
|
ldns_str2period(const char *nptr, const char **endptr)
|
|
{
|
|
int sign = 0;
|
|
uint32_t i = 0;
|
|
uint32_t seconds = 0;
|
|
|
|
for(*endptr = nptr; **endptr; (*endptr)++) {
|
|
switch (**endptr) {
|
|
case ' ':
|
|
case '\t':
|
|
break;
|
|
case '-':
|
|
if(sign == 0) {
|
|
sign = -1;
|
|
} else {
|
|
return seconds;
|
|
}
|
|
break;
|
|
case '+':
|
|
if(sign == 0) {
|
|
sign = 1;
|
|
} else {
|
|
return seconds;
|
|
}
|
|
break;
|
|
case 's':
|
|
case 'S':
|
|
seconds += i;
|
|
i = 0;
|
|
break;
|
|
case 'm':
|
|
case 'M':
|
|
seconds += i * 60;
|
|
i = 0;
|
|
break;
|
|
case 'h':
|
|
case 'H':
|
|
seconds += i * 60 * 60;
|
|
i = 0;
|
|
break;
|
|
case 'd':
|
|
case 'D':
|
|
seconds += i * 60 * 60 * 24;
|
|
i = 0;
|
|
break;
|
|
case 'w':
|
|
case 'W':
|
|
seconds += i * 60 * 60 * 24 * 7;
|
|
i = 0;
|
|
break;
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
i *= 10;
|
|
i += (**endptr - '0');
|
|
break;
|
|
default:
|
|
seconds += i;
|
|
/* disregard signedness */
|
|
return seconds;
|
|
}
|
|
}
|
|
seconds += i;
|
|
/* disregard signedness */
|
|
return seconds;
|
|
}
|