freebsd-dev/contrib/ldns/host2str.c
Dag-Erling Smørgrav 986ba33c7a Upgrade LDNS to 1.7.0.
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.
2018-05-12 12:00:18 +00:00

2557 lines
68 KiB
C

/*
* host2str.c
*
* conversion routines from the host format
* to the presentation format (strings)
*
* 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>
#include <limits.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include <time.h>
#include <sys/time.h>
#ifndef INET_ADDRSTRLEN
#define INET_ADDRSTRLEN 16
#endif
#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 46
#endif
/* lookup tables for standard DNS stuff */
/* Taken from RFC 2535, section 7. */
ldns_lookup_table ldns_algorithms[] = {
{ LDNS_RSAMD5, "RSAMD5" },
{ LDNS_DH, "DH" },
{ LDNS_DSA, "DSA" },
{ LDNS_ECC, "ECC" },
{ LDNS_RSASHA1, "RSASHA1" },
{ LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" },
{ LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
#ifdef USE_SHA2
{ LDNS_RSASHA256, "RSASHA256"},
{ LDNS_RSASHA512, "RSASHA512"},
#endif
#ifdef USE_GOST
{ LDNS_ECC_GOST, "ECC-GOST"},
#endif
#ifdef USE_ECDSA
{ LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
{ LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
#endif
#ifdef USE_ED25519
{ LDNS_ED25519, "ED25519"},
#endif
#ifdef USE_ED448
{ LDNS_ED448, "ED448"},
#endif
{ LDNS_INDIRECT, "INDIRECT" },
{ LDNS_PRIVATEDNS, "PRIVATEDNS" },
{ LDNS_PRIVATEOID, "PRIVATEOID" },
{ 0, NULL }
};
/* Taken from RFC 4398 */
ldns_lookup_table ldns_cert_algorithms[] = {
{ LDNS_CERT_PKIX, "PKIX" },
{ LDNS_CERT_SPKI, "SPKI" },
{ LDNS_CERT_PGP, "PGP" },
{ LDNS_CERT_IPKIX, "IPKIX" },
{ LDNS_CERT_ISPKI, "ISPKI" },
{ LDNS_CERT_IPGP, "IPGP" },
{ LDNS_CERT_ACPKIX, "ACPKIX" },
{ LDNS_CERT_IACPKIX, "IACPKIX" },
{ LDNS_CERT_URI, "URI" },
{ LDNS_CERT_OID, "OID" },
{ 0, NULL }
};
/* classes */
ldns_lookup_table ldns_rr_classes[] = {
{ LDNS_RR_CLASS_IN, "IN" },
{ LDNS_RR_CLASS_CH, "CH" },
{ LDNS_RR_CLASS_HS, "HS" },
{ LDNS_RR_CLASS_NONE, "NONE" },
{ LDNS_RR_CLASS_ANY, "ANY" },
{ 0, NULL }
};
/* if these are used elsewhere */
ldns_lookup_table ldns_rcodes[] = {
{ LDNS_RCODE_NOERROR, "NOERROR" },
{ LDNS_RCODE_FORMERR, "FORMERR" },
{ LDNS_RCODE_SERVFAIL, "SERVFAIL" },
{ LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
{ LDNS_RCODE_NOTIMPL, "NOTIMPL" },
{ LDNS_RCODE_REFUSED, "REFUSED" },
{ LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
{ LDNS_RCODE_YXRRSET, "YXRRSET" },
{ LDNS_RCODE_NXRRSET, "NXRRSET" },
{ LDNS_RCODE_NOTAUTH, "NOTAUTH" },
{ LDNS_RCODE_NOTZONE, "NOTZONE" },
{ 0, NULL }
};
ldns_lookup_table ldns_opcodes[] = {
{ LDNS_PACKET_QUERY, "QUERY" },
{ LDNS_PACKET_IQUERY, "IQUERY" },
{ LDNS_PACKET_STATUS, "STATUS" },
{ LDNS_PACKET_NOTIFY, "NOTIFY" },
{ LDNS_PACKET_UPDATE, "UPDATE" },
{ 0, NULL }
};
const ldns_output_format ldns_output_format_nocomments_record = { 0, NULL };
const ldns_output_format *ldns_output_format_nocomments
= &ldns_output_format_nocomments_record;
const ldns_output_format ldns_output_format_onlykeyids_record = {
LDNS_COMMENT_KEY, NULL
};
const ldns_output_format *ldns_output_format_onlykeyids
= &ldns_output_format_onlykeyids_record;
const ldns_output_format *ldns_output_format_default
= &ldns_output_format_onlykeyids_record;
const ldns_output_format ldns_output_format_bubblebabble_record = {
LDNS_COMMENT_KEY | LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS, NULL
};
const ldns_output_format *ldns_output_format_bubblebabble
= &ldns_output_format_bubblebabble_record;
static bool
ldns_output_format_covers_type(const ldns_output_format* fmt, ldns_rr_type t)
{
return fmt && (fmt->flags & LDNS_FMT_RFC3597) &&
((ldns_output_format_storage*)fmt)->bitmap &&
ldns_nsec_bitmap_covers_type(
((ldns_output_format_storage*)fmt)->bitmap, t);
}
ldns_status
ldns_output_format_set_type(ldns_output_format* fmt, ldns_rr_type t)
{
ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
ldns_status s;
assert(fmt != NULL);
if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
}
if (! fmt_st->bitmap) {
s = ldns_rdf_bitmap_known_rr_types_space(&fmt_st->bitmap);
if (s != LDNS_STATUS_OK) {
return s;
}
}
return ldns_nsec_bitmap_set_type(fmt_st->bitmap, t);
}
ldns_status
ldns_output_format_clear_type(ldns_output_format* fmt, ldns_rr_type t)
{
ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
ldns_status s;
assert(fmt != NULL);
if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
}
if (! fmt_st->bitmap) {
s = ldns_rdf_bitmap_known_rr_types(&fmt_st->bitmap);
if (s != LDNS_STATUS_OK) {
return s;
}
}
return ldns_nsec_bitmap_clear_type(fmt_st->bitmap, t);
}
ldns_status
ldns_pkt_opcode2buffer_str(ldns_buffer *output, ldns_pkt_opcode opcode)
{
ldns_lookup_table *lt = ldns_lookup_by_id(ldns_opcodes, opcode);
if (lt && lt->name) {
ldns_buffer_printf(output, "%s", lt->name);
} else {
ldns_buffer_printf(output, "OPCODE%u", opcode);
}
return ldns_buffer_status(output);
}
ldns_status
ldns_pkt_rcode2buffer_str(ldns_buffer *output, ldns_pkt_rcode rcode)
{
ldns_lookup_table *lt = ldns_lookup_by_id(ldns_rcodes, rcode);
if (lt && lt->name) {
ldns_buffer_printf(output, "%s", lt->name);
} else {
ldns_buffer_printf(output, "RCODE%u", rcode);
}
return ldns_buffer_status(output);
}
ldns_status
ldns_algorithm2buffer_str(ldns_buffer *output,
ldns_algorithm algorithm)
{
ldns_lookup_table *lt = ldns_lookup_by_id(ldns_algorithms,
algorithm);
if (lt && lt->name) {
ldns_buffer_printf(output, "%s", lt->name);
} else {
ldns_buffer_printf(output, "ALG%u", algorithm);
}
return ldns_buffer_status(output);
}
ldns_status
ldns_cert_algorithm2buffer_str(ldns_buffer *output,
ldns_cert_algorithm cert_algorithm)
{
ldns_lookup_table *lt = ldns_lookup_by_id(ldns_cert_algorithms,
cert_algorithm);
if (lt && lt->name) {
ldns_buffer_printf(output, "%s", lt->name);
} else {
ldns_buffer_printf(output, "CERT_ALG%u",
cert_algorithm);
}
return ldns_buffer_status(output);
}
char *
ldns_pkt_opcode2str(ldns_pkt_opcode opcode)
{
char *str;
ldns_buffer *buf;
buf = ldns_buffer_new(12);
if (!buf) {
return NULL;
}
str = NULL;
if (ldns_pkt_opcode2buffer_str(buf, opcode) == LDNS_STATUS_OK) {
str = ldns_buffer_export2str(buf);
}
ldns_buffer_free(buf);
return str;
}
char *
ldns_pkt_rcode2str(ldns_pkt_rcode rcode)
{
char *str;
ldns_buffer *buf;
buf = ldns_buffer_new(10);
if (!buf) {
return NULL;
}
str = NULL;
if (ldns_pkt_rcode2buffer_str(buf, rcode) == LDNS_STATUS_OK) {
str = ldns_buffer_export2str(buf);
}
ldns_buffer_free(buf);
return str;
}
char *
ldns_pkt_algorithm2str(ldns_algorithm algorithm)
{
char *str;
ldns_buffer *buf;
buf = ldns_buffer_new(10);
if (!buf) {
return NULL;
}
str = NULL;
if (ldns_algorithm2buffer_str(buf, algorithm)
== LDNS_STATUS_OK) {
str = ldns_buffer_export2str(buf);
}
ldns_buffer_free(buf);
return str;
}
char *
ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm)
{
char *str;
ldns_buffer *buf;
buf = ldns_buffer_new(10);
if (!buf) {
return NULL;
}
str = NULL;
if (ldns_cert_algorithm2buffer_str(buf, cert_algorithm)
== LDNS_STATUS_OK) {
str = ldns_buffer_export2str(buf);
}
ldns_buffer_free(buf);
return str;
}
/* do NOT pass compressed data here :p */
ldns_status
ldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname)
{
/* can we do with 1 pos var? or without at all? */
uint8_t src_pos = 0;
uint8_t len;
uint8_t *data;
uint8_t i;
unsigned char c;
data = (uint8_t*)ldns_rdf_data(dname);
len = data[src_pos];
if (ldns_rdf_size(dname) > LDNS_MAX_DOMAINLEN) {
/* too large, return */
return LDNS_STATUS_DOMAINNAME_OVERFLOW;
}
/* special case: root label */
if (1 == ldns_rdf_size(dname)) {
ldns_buffer_printf(output, ".");
} else {
while ((len > 0) && src_pos < ldns_rdf_size(dname)) {
src_pos++;
for(i = 0; i < len; i++) {
/* paranoia check for various 'strange'
characters in dnames
*/
c = (unsigned char) data[src_pos];
if(c == '.' || c == ';' ||
c == '(' || c == ')' ||
c == '\\') {
ldns_buffer_printf(output, "\\%c",
data[src_pos]);
} else if (!(isascii(c) && isgraph(c))) {
ldns_buffer_printf(output, "\\%03u",
data[src_pos]);
} else {
ldns_buffer_printf(output, "%c", data[src_pos]);
}
src_pos++;
}
if (src_pos < ldns_rdf_size(dname)) {
ldns_buffer_printf(output, ".");
}
len = data[src_pos];
}
}
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_int8(ldns_buffer *output, const ldns_rdf *rdf)
{
uint8_t data = ldns_rdf_data(rdf)[0];
ldns_buffer_printf(output, "%lu", (unsigned long) data);
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf)
{
uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
ldns_buffer_printf(output, "%lu", (unsigned long) data);
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf)
{
uint32_t data = ldns_read_uint32(ldns_rdf_data(rdf));
ldns_buffer_printf(output, "%lu", (unsigned long) data);
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf)
{
/* create a YYYYMMDDHHMMSS string if possible */
struct tm tm;
char date_buf[16];
memset(&tm, 0, sizeof(tm));
if (ldns_serial_arithmitics_gmtime_r(ldns_rdf2native_int32(rdf), time(NULL), &tm)
&& strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) {
ldns_buffer_printf(output, "%s", date_buf);
}
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_a(ldns_buffer *output, const ldns_rdf *rdf)
{
char str[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, ldns_rdf_data(rdf), str, INET_ADDRSTRLEN)) {
ldns_buffer_printf(output, "%s", str);
}
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_aaaa(ldns_buffer *output, const ldns_rdf *rdf)
{
char str[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET6, ldns_rdf_data(rdf), str, INET6_ADDRSTRLEN)) {
ldns_buffer_printf(output, "%s", str);
}
return ldns_buffer_status(output);
}
static void
ldns_characters2buffer_str(ldns_buffer* output,
size_t amount, const uint8_t* characters)
{
uint8_t ch;
while (amount > 0) {
ch = *characters++;
if (isprint((int)ch) || ch == '\t') {
if (ch == '\"' || ch == '\\')
ldns_buffer_printf(output, "\\%c", ch);
else
ldns_buffer_printf(output, "%c", ch);
} else {
ldns_buffer_printf(output, "\\%03u",
(unsigned)(uint8_t) ch);
}
amount--;
}
}
ldns_status
ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf)
{
if(ldns_rdf_size(rdf) < 1) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
if((int)ldns_rdf_size(rdf) < (int)ldns_rdf_data(rdf)[0] + 1) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
ldns_buffer_printf(output, "\"");
ldns_characters2buffer_str(output,
ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf) + 1);
ldns_buffer_printf(output, "\"");
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf)
{
size_t size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf));
char *b64 = LDNS_XMALLOC(char, size);
if(!b64) return LDNS_STATUS_MEM_ERR;
if (ldns_b64_ntop(ldns_rdf_data(rdf), ldns_rdf_size(rdf), b64, size)) {
ldns_buffer_printf(output, "%s", b64);
}
LDNS_FREE(b64);
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf)
{
size_t size;
char *b32;
if(ldns_rdf_size(rdf) == 0)
return LDNS_STATUS_OK;
/* remove -1 for the b32-hash-len octet */
size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
/* add one for the end nul for the string */
b32 = LDNS_XMALLOC(char, size + 1);
if(!b32) return LDNS_STATUS_MEM_ERR;
size = (size_t) ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1,
ldns_rdf_size(rdf) - 1, b32, size+1);
if (size > 0) {
ldns_buffer_printf(output, "%s", b32);
}
LDNS_FREE(b32);
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_hex(ldns_buffer *output, const ldns_rdf *rdf)
{
size_t i;
for (i = 0; i < ldns_rdf_size(rdf); i++) {
ldns_buffer_printf(output, "%02x", ldns_rdf_data(rdf)[i]);
}
return ldns_buffer_status(output);
}
static ldns_status
ldns_rdf2buffer_str_type_fmt(ldns_buffer *output,
const ldns_output_format* fmt, const ldns_rdf *rdf)
{
uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
if (! ldns_output_format_covers_type(fmt, data) &&
ldns_rr_descript(data) &&
ldns_rr_descript(data)->_name) {
ldns_buffer_printf(output, "%s",ldns_rr_descript(data)->_name);
} else {
ldns_buffer_printf(output, "TYPE%u", data);
}
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf)
{
return ldns_rdf2buffer_str_type_fmt(output,
ldns_output_format_default, rdf);
}
ldns_status
ldns_rdf2buffer_str_class(ldns_buffer *output, const ldns_rdf *rdf)
{
uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
ldns_lookup_table *lt;
lt = ldns_lookup_by_id(ldns_rr_classes, (int) data);
if (lt) {
ldns_buffer_printf(output, "\t%s", lt->name);
} else {
ldns_buffer_printf(output, "\tCLASS%d", data);
}
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_cert_alg(ldns_buffer *output, const ldns_rdf *rdf)
{
uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
ldns_lookup_table *lt;
lt = ldns_lookup_by_id(ldns_cert_algorithms, (int) data);
if (lt) {
ldns_buffer_printf(output, "%s", lt->name);
} else {
ldns_buffer_printf(output, "%d", data);
}
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf)
{
return ldns_rdf2buffer_str_int8(output, rdf);
}
static void
loc_cm_print(ldns_buffer *output, uint8_t mantissa, uint8_t exponent)
{
uint8_t i;
/* is it 0.<two digits> ? */
if(exponent < 2) {
if(exponent == 1)
mantissa *= 10;
ldns_buffer_printf(output, "0.%02ld", (long)mantissa);
return;
}
/* always <digit><string of zeros> */
ldns_buffer_printf(output, "%d", (int)mantissa);
for(i=0; i<exponent-2; i++)
ldns_buffer_printf(output, "0");
}
ldns_status
ldns_rr_type2buffer_str(ldns_buffer *output, const ldns_rr_type type)
{
const ldns_rr_descriptor *descriptor;
descriptor = ldns_rr_descript(type);
switch (type) {
case LDNS_RR_TYPE_IXFR:
ldns_buffer_printf(output, "IXFR");
break;
case LDNS_RR_TYPE_AXFR:
ldns_buffer_printf(output, "AXFR");
break;
case LDNS_RR_TYPE_MAILA:
ldns_buffer_printf(output, "MAILA");
break;
case LDNS_RR_TYPE_MAILB:
ldns_buffer_printf(output, "MAILB");
break;
case LDNS_RR_TYPE_ANY:
ldns_buffer_printf(output, "ANY");
break;
default:
if (descriptor && descriptor->_name) {
ldns_buffer_printf(output, "%s", descriptor->_name);
} else {
ldns_buffer_printf(output, "TYPE%u", type);
}
}
return ldns_buffer_status(output);
}
char *
ldns_rr_type2str(const ldns_rr_type type)
{
char *str;
ldns_buffer *buf;
buf = ldns_buffer_new(10);
if (!buf) {
return NULL;
}
str = NULL;
if (ldns_rr_type2buffer_str(buf, type) == LDNS_STATUS_OK) {
str = ldns_buffer_export2str(buf);
}
ldns_buffer_free(buf);
return str;
}
ldns_status
ldns_rr_class2buffer_str(ldns_buffer *output,
const ldns_rr_class klass)
{
ldns_lookup_table *lt;
lt = ldns_lookup_by_id(ldns_rr_classes, klass);
if (lt) {
ldns_buffer_printf(output, "%s", lt->name);
} else {
ldns_buffer_printf(output, "CLASS%d", klass);
}
return ldns_buffer_status(output);
}
char *
ldns_rr_class2str(const ldns_rr_class klass)
{
ldns_buffer *buf;
char *str;
buf = ldns_buffer_new(10);
if (!buf) {
return NULL;
}
str = NULL;
if (ldns_rr_class2buffer_str(buf, klass) == LDNS_STATUS_OK) {
str = ldns_buffer_export2str(buf);
}
ldns_buffer_free(buf);
return str;
}
ldns_status
ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf)
{
/* we could do checking (ie degrees < 90 etc)? */
uint8_t version;
uint8_t size;
uint8_t horizontal_precision;
uint8_t vertical_precision;
uint32_t longitude;
uint32_t latitude;
uint32_t altitude;
char northerness;
char easterness;
uint32_t h;
uint32_t m;
double s;
uint32_t equator = (uint32_t) ldns_power(2, 31);
if(ldns_rdf_size(rdf) < 1) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
version = ldns_rdf_data(rdf)[0];
if (version == 0) {
if(ldns_rdf_size(rdf) < 16) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
size = ldns_rdf_data(rdf)[1];
horizontal_precision = ldns_rdf_data(rdf)[2];
vertical_precision = ldns_rdf_data(rdf)[3];
latitude = ldns_read_uint32(&ldns_rdf_data(rdf)[4]);
longitude = ldns_read_uint32(&ldns_rdf_data(rdf)[8]);
altitude = ldns_read_uint32(&ldns_rdf_data(rdf)[12]);
if (latitude > equator) {
northerness = 'N';
latitude = latitude - equator;
} else {
northerness = 'S';
latitude = equator - latitude;
}
h = latitude / (1000 * 60 * 60);
latitude = latitude % (1000 * 60 * 60);
m = latitude / (1000 * 60);
latitude = latitude % (1000 * 60);
s = (double) latitude / 1000.0;
ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
h, m, s, northerness);
if (longitude > equator) {
easterness = 'E';
longitude = longitude - equator;
} else {
easterness = 'W';
longitude = equator - longitude;
}
h = longitude / (1000 * 60 * 60);
longitude = longitude % (1000 * 60 * 60);
m = longitude / (1000 * 60);
longitude = longitude % (1000 * 60);
s = (double) longitude / (1000.0);
ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
h, m, s, easterness);
s = ((double) altitude) / 100;
s -= 100000;
if(altitude%100 != 0)
ldns_buffer_printf(output, "%.2f", s);
else
ldns_buffer_printf(output, "%.0f", s);
ldns_buffer_printf(output, "m ");
loc_cm_print(output, (size & 0xf0) >> 4, size & 0x0f);
ldns_buffer_printf(output, "m ");
loc_cm_print(output, (horizontal_precision & 0xf0) >> 4,
horizontal_precision & 0x0f);
ldns_buffer_printf(output, "m ");
loc_cm_print(output, (vertical_precision & 0xf0) >> 4,
vertical_precision & 0x0f);
ldns_buffer_printf(output, "m");
return ldns_buffer_status(output);
} else {
return ldns_rdf2buffer_str_hex(output, rdf);
}
}
ldns_status
ldns_rdf2buffer_str_unknown(ldns_buffer *output, const ldns_rdf *rdf)
{
ldns_buffer_printf(output, "\\# %u ", ldns_rdf_size(rdf));
return ldns_rdf2buffer_str_hex(output, rdf);
}
ldns_status
ldns_rdf2buffer_str_nsap(ldns_buffer *output, const ldns_rdf *rdf)
{
ldns_buffer_printf(output, "0x");
return ldns_rdf2buffer_str_hex(output, rdf);
}
ldns_status
ldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf)
{
return ldns_rdf2buffer_str_hex(output, rdf);
}
ldns_status
ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf)
{
/* protocol, followed by bitmap of services */
struct protoent *protocol;
char *proto_name = NULL;
uint8_t protocol_nr;
struct servent *service;
uint16_t current_service;
if(ldns_rdf_size(rdf) < 1) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
protocol_nr = ldns_rdf_data(rdf)[0];
protocol = getprotobynumber((int) protocol_nr);
if (protocol && (protocol->p_name != NULL)) {
proto_name = protocol->p_name;
ldns_buffer_printf(output, "%s ", protocol->p_name);
} else {
ldns_buffer_printf(output, "%u ", protocol_nr);
}
#ifdef HAVE_ENDPROTOENT
endprotoent();
#endif
for (current_service = 0;
current_service < (ldns_rdf_size(rdf)-1)*8; current_service++) {
if (ldns_get_bit(&(ldns_rdf_data(rdf)[1]), current_service)) {
service = getservbyport((int) htons(current_service),
proto_name);
if (service && service->s_name) {
ldns_buffer_printf(output, "%s ", service->s_name);
} else {
ldns_buffer_printf(output, "%u ", current_service);
}
#ifdef HAVE_ENDSERVENT
endservent();
#endif
}
}
return ldns_buffer_status(output);
}
static ldns_status
ldns_rdf2buffer_str_nsec_fmt(ldns_buffer *output,
const ldns_output_format* fmt, const ldns_rdf *rdf)
{
/* Note: this code is duplicated in higher.c in
* ldns_nsec_type_check() function
*/
uint8_t window_block_nr;
uint8_t bitmap_length;
uint16_t type;
uint16_t pos = 0;
uint16_t bit_pos;
uint8_t *data = ldns_rdf_data(rdf);
while((size_t)(pos + 2) < ldns_rdf_size(rdf)) {
window_block_nr = data[pos];
bitmap_length = data[pos + 1];
pos += 2;
if (ldns_rdf_size(rdf) < pos + bitmap_length) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
if (! ldns_get_bit(&data[pos], bit_pos)) {
continue;
}
type = 256 * (uint16_t) window_block_nr + bit_pos;
if (! ldns_output_format_covers_type(fmt, type) &&
ldns_rr_descript(type) &&
ldns_rr_descript(type)->_name){
ldns_buffer_printf(output, "%s ",
ldns_rr_descript(type)->_name);
} else {
ldns_buffer_printf(output, "TYPE%u ", type);
}
}
pos += (uint16_t) bitmap_length;
}
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
{
return ldns_rdf2buffer_str_nsec_fmt(output,
ldns_output_format_default, rdf);
}
ldns_status
ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf)
{
uint8_t salt_length;
uint8_t salt_pos;
uint8_t *data = ldns_rdf_data(rdf);
if(ldns_rdf_size(rdf) < 1) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
salt_length = data[0];
/* from now there are variable length entries so remember pos */
if (salt_length == 0 || ((size_t)salt_length)+1 > ldns_rdf_size(rdf)) {
ldns_buffer_printf(output, "- ");
} else {
for (salt_pos = 0; salt_pos < salt_length; salt_pos++) {
ldns_buffer_printf(output, "%02x", data[1 + salt_pos]);
}
ldns_buffer_printf(output, " ");
}
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_period(ldns_buffer *output, const ldns_rdf *rdf)
{
/* period is the number of seconds */
if (ldns_rdf_size(rdf) != 4) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
ldns_buffer_printf(output, "%u", ldns_read_uint32(ldns_rdf_data(rdf)));
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_tsigtime(ldns_buffer *output,const ldns_rdf *rdf)
{
/* tsigtime is 48 bits network order unsigned integer */
uint64_t tsigtime = 0;
uint8_t *data = ldns_rdf_data(rdf);
uint64_t d0, d1, d2, d3, d4, d5;
if (ldns_rdf_size(rdf) < 6) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
d0 = data[0]; /* cast to uint64 for shift operations */
d1 = data[1];
d2 = data[2];
d3 = data[3];
d4 = data[4];
d5 = data[5];
tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
ldns_buffer_printf(output, "%llu ", (long long)tsigtime);
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf)
{
uint8_t *data = ldns_rdf_data(rdf);
uint16_t address_family;
uint8_t prefix;
bool negation;
uint8_t adf_length;
size_t i;
size_t pos = 0;
while (pos < (unsigned int) ldns_rdf_size(rdf)) {
if(pos + 3 >= (unsigned)ldns_rdf_size(rdf))
return LDNS_STATUS_WIRE_RDATA_ERR;
address_family = ldns_read_uint16(&data[pos]);
prefix = data[pos + 2];
negation = data[pos + 3] & LDNS_APL_NEGATION;
adf_length = data[pos + 3] & LDNS_APL_MASK;
if (address_family == LDNS_APL_IP4) {
/* check if prefix < 32? */
if (negation) {
ldns_buffer_printf(output, "!");
}
ldns_buffer_printf(output, "%u:", address_family);
/* address is variable length 0 - 4 */
for (i = 0; i < 4; i++) {
if (i > 0) {
ldns_buffer_printf(output, ".");
}
if (i < (unsigned short) adf_length) {
if(pos+i+4 >= ldns_rdf_size(rdf))
return LDNS_STATUS_WIRE_RDATA_ERR;
ldns_buffer_printf(output, "%d",
data[pos + i + 4]);
} else {
ldns_buffer_printf(output, "0");
}
}
ldns_buffer_printf(output, "/%u ", prefix);
} else if (address_family == LDNS_APL_IP6) {
/* check if prefix < 128? */
if (negation) {
ldns_buffer_printf(output, "!");
}
ldns_buffer_printf(output, "%u:", address_family);
/* address is variable length 0 - 16 */
for (i = 0; i < 16; i++) {
if (i % 2 == 0 && i > 0) {
ldns_buffer_printf(output, ":");
}
if (i < (unsigned short) adf_length) {
if(pos+i+4 >= ldns_rdf_size(rdf))
return LDNS_STATUS_WIRE_RDATA_ERR;
ldns_buffer_printf(output, "%02x",
data[pos + i + 4]);
} else {
ldns_buffer_printf(output, "00");
}
}
ldns_buffer_printf(output, "/%u ", prefix);
} else {
/* unknown address family */
ldns_buffer_printf(output,
"Unknown address family: %u data: ",
address_family);
for (i = 1; i < (unsigned short) (4 + adf_length); i++) {
if(pos+i >= ldns_rdf_size(rdf))
return LDNS_STATUS_WIRE_RDATA_ERR;
ldns_buffer_printf(output, "%02x", data[i]);
}
}
pos += 4 + adf_length;
}
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_int16_data(ldns_buffer *output, const ldns_rdf *rdf)
{
size_t size;
char *b64;
if (ldns_rdf_size(rdf) < 2) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
/* Subtract the size (2) of the number that specifies the length */
size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf) - 2);
ldns_buffer_printf(output, "%u ", ldns_rdf_size(rdf) - 2);
if (ldns_rdf_size(rdf) > 2) {
b64 = LDNS_XMALLOC(char, size);
if(!b64)
return LDNS_STATUS_MEM_ERR;
if (ldns_rdf_size(rdf) > 2 &&
ldns_b64_ntop(ldns_rdf_data(rdf) + 2,
ldns_rdf_size(rdf) - 2,
b64, size)) {
ldns_buffer_printf(output, "%s", b64);
}
LDNS_FREE(b64);
}
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf)
{
/* wire format from
http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt
*/
uint8_t *data = ldns_rdf_data(rdf);
uint8_t precedence;
uint8_t gateway_type;
uint8_t algorithm;
ldns_rdf *gateway = NULL;
uint8_t *gateway_data;
size_t public_key_size;
uint8_t *public_key_data;
ldns_rdf *public_key;
size_t offset = 0;
ldns_status status;
if (ldns_rdf_size(rdf) < 3) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
precedence = data[0];
gateway_type = data[1];
algorithm = data[2];
offset = 3;
switch (gateway_type) {
case 0:
/* no gateway */
break;
case 1:
gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP4ADDRLEN);
if(!gateway_data)
return LDNS_STATUS_MEM_ERR;
if (ldns_rdf_size(rdf) < offset + LDNS_IP4ADDRLEN) {
return LDNS_STATUS_ERR;
}
memcpy(gateway_data, &data[offset], LDNS_IP4ADDRLEN);
gateway = ldns_rdf_new(LDNS_RDF_TYPE_A,
LDNS_IP4ADDRLEN , gateway_data);
offset += LDNS_IP4ADDRLEN;
if(!gateway) {
LDNS_FREE(gateway_data);
return LDNS_STATUS_MEM_ERR;
}
break;
case 2:
gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP6ADDRLEN);
if(!gateway_data)
return LDNS_STATUS_MEM_ERR;
if (ldns_rdf_size(rdf) < offset + LDNS_IP6ADDRLEN) {
return LDNS_STATUS_ERR;
}
memcpy(gateway_data, &data[offset], LDNS_IP6ADDRLEN);
offset += LDNS_IP6ADDRLEN;
gateway =
ldns_rdf_new(LDNS_RDF_TYPE_AAAA,
LDNS_IP6ADDRLEN, gateway_data);
if(!gateway) {
LDNS_FREE(gateway_data);
return LDNS_STATUS_MEM_ERR;
}
break;
case 3:
status = ldns_wire2dname(&gateway, data,
ldns_rdf_size(rdf), &offset);
if(status != LDNS_STATUS_OK)
return status;
break;
default:
/* error? */
break;
}
if (ldns_rdf_size(rdf) <= offset) {
return LDNS_STATUS_ERR;
}
public_key_size = ldns_rdf_size(rdf) - offset;
public_key_data = LDNS_XMALLOC(uint8_t, public_key_size);
if(!public_key_data) {
ldns_rdf_deep_free(gateway);
return LDNS_STATUS_MEM_ERR;
}
memcpy(public_key_data, &data[offset], public_key_size);
public_key = ldns_rdf_new(LDNS_RDF_TYPE_B64,
public_key_size, public_key_data);
if(!public_key) {
LDNS_FREE(public_key_data);
ldns_rdf_deep_free(gateway);
return LDNS_STATUS_MEM_ERR;
}
ldns_buffer_printf(output, "%u %u %u ", precedence, gateway_type, algorithm);
if (gateway)
(void) ldns_rdf2buffer_str(output, gateway);
else
ldns_buffer_printf(output, ".");
ldns_buffer_printf(output, " ");
(void) ldns_rdf2buffer_str(output, public_key);
ldns_rdf_deep_free(gateway);
ldns_rdf_deep_free(public_key);
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_ilnp64(ldns_buffer *output, const ldns_rdf *rdf)
{
if (ldns_rdf_size(rdf) != 8) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
ldns_buffer_printf(output,"%.4x:%.4x:%.4x:%.4x",
ldns_read_uint16(ldns_rdf_data(rdf)),
ldns_read_uint16(ldns_rdf_data(rdf)+2),
ldns_read_uint16(ldns_rdf_data(rdf)+4),
ldns_read_uint16(ldns_rdf_data(rdf)+6));
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_eui48(ldns_buffer *output, const ldns_rdf *rdf)
{
if (ldns_rdf_size(rdf) != 6) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
ldns_buffer_printf(output,"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf)[1],
ldns_rdf_data(rdf)[2], ldns_rdf_data(rdf)[3],
ldns_rdf_data(rdf)[4], ldns_rdf_data(rdf)[5]);
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_eui64(ldns_buffer *output, const ldns_rdf *rdf)
{
if (ldns_rdf_size(rdf) != 8) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
ldns_buffer_printf(output,"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf)[1],
ldns_rdf_data(rdf)[2], ldns_rdf_data(rdf)[3],
ldns_rdf_data(rdf)[4], ldns_rdf_data(rdf)[5],
ldns_rdf_data(rdf)[6], ldns_rdf_data(rdf)[7]);
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_tag(ldns_buffer *output, const ldns_rdf *rdf)
{
size_t nchars;
const uint8_t* chars;
char ch;
if (ldns_rdf_size(rdf) < 2) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
nchars = ldns_rdf_data(rdf)[0];
if (nchars >= ldns_rdf_size(rdf) || /* should be rdf_size - 1 */
nchars < 1) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
chars = ldns_rdf_data(rdf) + 1;
while (nchars > 0) {
ch = (char)*chars++;
if (! isalnum((unsigned char)ch)) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
ldns_buffer_printf(output, "%c", ch);
nchars--;
}
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_long_str(ldns_buffer *output, const ldns_rdf *rdf)
{
ldns_buffer_printf(output, "\"");
ldns_characters2buffer_str(output,
ldns_rdf_size(rdf), ldns_rdf_data(rdf));
ldns_buffer_printf(output, "\"");
return ldns_buffer_status(output);
}
ldns_status
ldns_rdf2buffer_str_hip(ldns_buffer *output, const ldns_rdf *rdf)
{
uint8_t *data = ldns_rdf_data(rdf);
size_t rdf_size = ldns_rdf_size(rdf);
uint8_t hit_size;
uint16_t pk_size;
int written;
if (rdf_size < 6) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
if ((hit_size = data[0]) == 0 ||
(pk_size = ldns_read_uint16(data + 2)) == 0 ||
rdf_size < (size_t) hit_size + pk_size + 4) {
return LDNS_STATUS_WIRE_RDATA_ERR;
}
ldns_buffer_printf(output, "%d ", (int) data[1]);
for (data += 4; hit_size > 0; hit_size--, data++) {
ldns_buffer_printf(output, "%02x", (int) *data);
}
ldns_buffer_write_u8(output, (uint8_t) ' ');
if (ldns_buffer_reserve(output,
ldns_b64_ntop_calculate_size(pk_size))) {
written = ldns_b64_ntop(data, pk_size,
(char *) ldns_buffer_current(output),
ldns_buffer_remaining(output));
if (written > 0 &&
written < (int) ldns_buffer_remaining(output)) {
output->_position += written;
}
}
return ldns_buffer_status(output);
}
static ldns_status
ldns_rdf2buffer_str_fmt(ldns_buffer *buffer,
const ldns_output_format* fmt, const ldns_rdf *rdf)
{
ldns_status res = LDNS_STATUS_OK;
/*ldns_buffer_printf(buffer, "%u:", ldns_rdf_get_type(rdf));*/
if (rdf) {
switch(ldns_rdf_get_type(rdf)) {
case LDNS_RDF_TYPE_NONE:
break;
case LDNS_RDF_TYPE_DNAME:
res = ldns_rdf2buffer_str_dname(buffer, rdf);
break;
case LDNS_RDF_TYPE_INT8: /* Don't output mnemonics for these */
case LDNS_RDF_TYPE_ALG:
case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
case LDNS_RDF_TYPE_SELECTOR:
case LDNS_RDF_TYPE_MATCHING_TYPE:
res = ldns_rdf2buffer_str_int8(buffer, rdf);
break;
case LDNS_RDF_TYPE_INT16:
res = ldns_rdf2buffer_str_int16(buffer, rdf);
break;
case LDNS_RDF_TYPE_INT32:
res = ldns_rdf2buffer_str_int32(buffer, rdf);
break;
case LDNS_RDF_TYPE_PERIOD:
res = ldns_rdf2buffer_str_period(buffer, rdf);
break;
case LDNS_RDF_TYPE_TSIGTIME:
res = ldns_rdf2buffer_str_tsigtime(buffer, rdf);
break;
case LDNS_RDF_TYPE_A:
res = ldns_rdf2buffer_str_a(buffer, rdf);
break;
case LDNS_RDF_TYPE_AAAA:
res = ldns_rdf2buffer_str_aaaa(buffer, rdf);
break;
case LDNS_RDF_TYPE_STR:
res = ldns_rdf2buffer_str_str(buffer, rdf);
break;
case LDNS_RDF_TYPE_APL:
res = ldns_rdf2buffer_str_apl(buffer, rdf);
break;
case LDNS_RDF_TYPE_B32_EXT:
res = ldns_rdf2buffer_str_b32_ext(buffer, rdf);
break;
case LDNS_RDF_TYPE_B64:
res = ldns_rdf2buffer_str_b64(buffer, rdf);
break;
case LDNS_RDF_TYPE_HEX:
res = ldns_rdf2buffer_str_hex(buffer, rdf);
break;
case LDNS_RDF_TYPE_NSEC:
res = ldns_rdf2buffer_str_nsec_fmt(buffer, fmt, rdf);
break;
case LDNS_RDF_TYPE_NSEC3_SALT:
res = ldns_rdf2buffer_str_nsec3_salt(buffer, rdf);
break;
case LDNS_RDF_TYPE_TYPE:
res = ldns_rdf2buffer_str_type_fmt(buffer, fmt, rdf);
break;
case LDNS_RDF_TYPE_CLASS:
res = ldns_rdf2buffer_str_class(buffer, rdf);
break;
case LDNS_RDF_TYPE_CERT_ALG:
res = ldns_rdf2buffer_str_cert_alg(buffer, rdf);
break;
case LDNS_RDF_TYPE_UNKNOWN:
res = ldns_rdf2buffer_str_unknown(buffer, rdf);
break;
case LDNS_RDF_TYPE_TIME:
res = ldns_rdf2buffer_str_time(buffer, rdf);
break;
case LDNS_RDF_TYPE_HIP:
res = ldns_rdf2buffer_str_hip(buffer, rdf);
break;
case LDNS_RDF_TYPE_LOC:
res = ldns_rdf2buffer_str_loc(buffer, rdf);
break;
case LDNS_RDF_TYPE_WKS:
case LDNS_RDF_TYPE_SERVICE:
res = ldns_rdf2buffer_str_wks(buffer, rdf);
break;
case LDNS_RDF_TYPE_NSAP:
res = ldns_rdf2buffer_str_nsap(buffer, rdf);
break;
case LDNS_RDF_TYPE_ATMA:
res = ldns_rdf2buffer_str_atma(buffer, rdf);
break;
case LDNS_RDF_TYPE_IPSECKEY:
res = ldns_rdf2buffer_str_ipseckey(buffer, rdf);
break;
case LDNS_RDF_TYPE_INT16_DATA:
res = ldns_rdf2buffer_str_int16_data(buffer, rdf);
break;
case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
res = ldns_rdf2buffer_str_b32_ext(buffer, rdf);
break;
case LDNS_RDF_TYPE_ILNP64:
res = ldns_rdf2buffer_str_ilnp64(buffer, rdf);
break;
case LDNS_RDF_TYPE_EUI48:
res = ldns_rdf2buffer_str_eui48(buffer, rdf);
break;
case LDNS_RDF_TYPE_EUI64:
res = ldns_rdf2buffer_str_eui64(buffer, rdf);
break;
case LDNS_RDF_TYPE_TAG:
res = ldns_rdf2buffer_str_tag(buffer, rdf);
break;
case LDNS_RDF_TYPE_LONG_STR:
res = ldns_rdf2buffer_str_long_str(buffer, rdf);
break;
}
} else {
/** This will write mangled RRs */
ldns_buffer_printf(buffer, "(null) ");
res = LDNS_STATUS_ERR;
}
return res;
}
ldns_status
ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
{
return ldns_rdf2buffer_str_fmt(buffer,ldns_output_format_default,rdf);
}
static ldns_rdf *
ldns_b32_ext2dname(const ldns_rdf *rdf)
{
size_t size;
char *b32;
ldns_rdf *out;
if(ldns_rdf_size(rdf) == 0)
return NULL;
/* remove -1 for the b32-hash-len octet */
size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
/* add one for the end nul for the string */
b32 = LDNS_XMALLOC(char, size + 2);
if (b32) {
if (ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1,
ldns_rdf_size(rdf) - 1, b32, size+1) > 0) {
b32[size] = '.';
b32[size+1] = '\0';
if (ldns_str2rdf_dname(&out, b32) == LDNS_STATUS_OK) {
LDNS_FREE(b32);
return out;
}
}
LDNS_FREE(b32);
}
return NULL;
}
static ldns_status
ldns_rr2buffer_str_rfc3597(ldns_buffer *output, const ldns_rr *rr)
{
size_t total_rdfsize = 0;
size_t i, j;
ldns_buffer_printf(output, "TYPE%u\t", ldns_rr_get_type(rr));
for (i = 0; i < ldns_rr_rd_count(rr); i++) {
total_rdfsize += ldns_rdf_size(ldns_rr_rdf(rr, i));
}
if (total_rdfsize == 0) {
ldns_buffer_printf(output, "\\# 0\n");
return ldns_buffer_status(output);
}
ldns_buffer_printf(output, "\\# %d ", total_rdfsize);
for (i = 0; i < ldns_rr_rd_count(rr); i++) {
for (j = 0; j < ldns_rdf_size(ldns_rr_rdf(rr, i)); j++) {
ldns_buffer_printf(output, "%.2x",
ldns_rdf_data(ldns_rr_rdf(rr, i))[j]);
}
}
ldns_buffer_printf(output, "\n");
return ldns_buffer_status(output);
}
ldns_status
ldns_rr2buffer_str_fmt(ldns_buffer *output,
const ldns_output_format *fmt, const ldns_rr *rr)
{
uint16_t i, flags;
ldns_status status = LDNS_STATUS_OK;
ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
if (fmt_st == NULL) {
fmt_st = (ldns_output_format_storage*)
ldns_output_format_default;
}
if (!rr) {
if (LDNS_COMMENT_NULLS & fmt_st->flags) {
ldns_buffer_printf(output, "; (null)\n");
}
return ldns_buffer_status(output);
}
if (ldns_rr_owner(rr)) {
status = ldns_rdf2buffer_str_dname(output, ldns_rr_owner(rr));
}
if (status != LDNS_STATUS_OK) {
return status;
}
/* TTL should NOT be printed if it is a question */
if (!ldns_rr_is_question(rr)) {
ldns_buffer_printf(output, "\t%d", ldns_rr_ttl(rr));
}
ldns_buffer_printf(output, "\t");
status = ldns_rr_class2buffer_str(output, ldns_rr_get_class(rr));
if (status != LDNS_STATUS_OK) {
return status;
}
ldns_buffer_printf(output, "\t");
if (ldns_output_format_covers_type(fmt, ldns_rr_get_type(rr))) {
return ldns_rr2buffer_str_rfc3597(output, rr);
}
status = ldns_rr_type2buffer_str(output, ldns_rr_get_type(rr));
if (status != LDNS_STATUS_OK) {
return status;
}
if (ldns_rr_rd_count(rr) > 0) {
ldns_buffer_printf(output, "\t");
} else if (!ldns_rr_is_question(rr)) {
ldns_buffer_printf(output, "\t\\# 0");
}
for (i = 0; i < ldns_rr_rd_count(rr); i++) {
/* ldns_rdf2buffer_str handles NULL input fine! */
if ((fmt_st->flags & LDNS_FMT_ZEROIZE_RRSIGS) &&
(ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) &&
((/* inception */ i == 4 &&
ldns_rdf_get_type(ldns_rr_rdf(rr, 4)) ==
LDNS_RDF_TYPE_TIME) ||
(/* expiration */ i == 5 &&
ldns_rdf_get_type(ldns_rr_rdf(rr, 5)) ==
LDNS_RDF_TYPE_TIME) ||
(/* signature */ i == 8 &&
ldns_rdf_get_type(ldns_rr_rdf(rr, 8)) ==
LDNS_RDF_TYPE_B64))) {
ldns_buffer_printf(output, "(null)");
status = ldns_buffer_status(output);
} else if ((fmt_st->flags & LDNS_FMT_PAD_SOA_SERIAL) &&
(ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) &&
/* serial */ i == 2 &&
ldns_rdf_get_type(ldns_rr_rdf(rr, 2)) ==
LDNS_RDF_TYPE_INT32) {
ldns_buffer_printf(output, "%10lu",
(unsigned long) ldns_read_uint32(
ldns_rdf_data(ldns_rr_rdf(rr, 2))));
status = ldns_buffer_status(output);
} else {
status = ldns_rdf2buffer_str_fmt(output,
fmt, ldns_rr_rdf(rr, i));
}
if(status != LDNS_STATUS_OK)
return status;
if (i < ldns_rr_rd_count(rr) - 1) {
ldns_buffer_printf(output, " ");
}
}
/* per RR special comments - handy for DNSSEC types */
/* check to prevent question sec. rr from
* getting here */
if (ldns_rr_rd_count(rr) > 0) {
switch (ldns_rr_get_type(rr)) {
case LDNS_RR_TYPE_DNSKEY:
/* if ldns_rr_rd_count(rr) > 0
then ldns_rr_rdf(rr, 0) exists! */
if (! (fmt_st->flags & LDNS_COMMENT_KEY)) {
break;
}
flags = ldns_rdf2native_int16(ldns_rr_rdf(rr, 0));
ldns_buffer_printf(output, " ;{");
if (fmt_st->flags & LDNS_COMMENT_KEY_ID) {
ldns_buffer_printf(output, "id = %u",
(unsigned int) ldns_calc_keytag(rr));
}
if ((fmt_st->flags & LDNS_COMMENT_KEY_TYPE) &&
(flags & LDNS_KEY_ZONE_KEY)){
if (flags & LDNS_KEY_SEP_KEY) {
ldns_buffer_printf(output, " (ksk)");
} else {
ldns_buffer_printf(output, " (zsk)");
}
if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE){
ldns_buffer_printf(output, ", ");
}
} else if (fmt_st->flags
& (LDNS_COMMENT_KEY_ID
|LDNS_COMMENT_KEY_SIZE)) {
ldns_buffer_printf( output, ", ");
}
if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE) {
ldns_buffer_printf(output, "size = %db",
ldns_rr_dnskey_key_size(rr));
}
ldns_buffer_printf(output, "}");
break;
case LDNS_RR_TYPE_RRSIG:
if ((fmt_st->flags & LDNS_COMMENT_KEY)
&& (fmt_st->flags& LDNS_COMMENT_RRSIGS)
&& ldns_rr_rdf(rr, 6) != NULL) {
ldns_buffer_printf(output, " ;{id = %d}",
ldns_rdf2native_int16(
ldns_rr_rdf(rr, 6)));
}
break;
case LDNS_RR_TYPE_DS:
if ((fmt_st->flags & LDNS_COMMENT_BUBBLEBABBLE) &&
ldns_rr_rdf(rr, 3) != NULL) {
uint8_t *data = ldns_rdf_data(
ldns_rr_rdf(rr, 3));
size_t len = ldns_rdf_size(ldns_rr_rdf(rr, 3));
char *babble = ldns_bubblebabble(data, len);
if(babble) {
ldns_buffer_printf(output,
" ;{%s}", babble);
}
LDNS_FREE(babble);
}
break;
case LDNS_RR_TYPE_NSEC3:
if (! (fmt_st->flags & LDNS_COMMENT_FLAGS) &&
! (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN)) {
break;
}
ldns_buffer_printf(output, " ;{");
if ((fmt_st->flags & LDNS_COMMENT_FLAGS)) {
if (ldns_nsec3_optout(rr)) {
ldns_buffer_printf(output,
" flags: optout");
} else {
ldns_buffer_printf(output," flags: -");
}
if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
fmt_st->hashmap != NULL) {
ldns_buffer_printf(output, ", ");
}
}
if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
fmt_st->hashmap != NULL) {
ldns_rbnode_t *node;
ldns_rdf *key = ldns_dname_label(
ldns_rr_owner(rr), 0);
if (key) {
node = ldns_rbtree_search(
fmt_st->hashmap,
(void *) key);
if (node->data) {
ldns_buffer_printf(output,
"from: ");
(void) ldns_rdf2buffer_str(
output,
ldns_dnssec_name_name(
(ldns_dnssec_name*)
node->data
));
}
ldns_rdf_free(key);
}
key = ldns_b32_ext2dname(
ldns_nsec3_next_owner(rr));
if (key) {
node = ldns_rbtree_search(
fmt_st->hashmap,
(void *) key);
if (node->data) {
ldns_buffer_printf(output,
" to: ");
(void) ldns_rdf2buffer_str(
output,
ldns_dnssec_name_name(
(ldns_dnssec_name*)
node->data
));
}
ldns_rdf_free(key);
}
}
ldns_buffer_printf(output, "}");
break;
default:
break;
}
}
/* last */
ldns_buffer_printf(output, "\n");
return ldns_buffer_status(output);
}
ldns_status
ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr)
{
return ldns_rr2buffer_str_fmt(output, ldns_output_format_default, rr);
}
ldns_status
ldns_rr_list2buffer_str_fmt(ldns_buffer *output,
const ldns_output_format *fmt, const ldns_rr_list *list)
{
uint16_t i;
for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
(void) ldns_rr2buffer_str_fmt(output, fmt,
ldns_rr_list_rr(list, i));
}
return ldns_buffer_status(output);
}
ldns_status
ldns_rr_list2buffer_str(ldns_buffer *output, const ldns_rr_list *list)
{
return ldns_rr_list2buffer_str_fmt(
output, ldns_output_format_default, list);
}
ldns_status
ldns_pktheader2buffer_str(ldns_buffer *output, const ldns_pkt *pkt)
{
ldns_lookup_table *opcode = ldns_lookup_by_id(ldns_opcodes,
(int) ldns_pkt_get_opcode(pkt));
ldns_lookup_table *rcode = ldns_lookup_by_id(ldns_rcodes,
(int) ldns_pkt_get_rcode(pkt));
ldns_buffer_printf(output, ";; ->>HEADER<<- ");
if (opcode) {
ldns_buffer_printf(output, "opcode: %s, ", opcode->name);
} else {
ldns_buffer_printf(output, "opcode: ?? (%u), ",
ldns_pkt_get_opcode(pkt));
}
if (rcode) {
ldns_buffer_printf(output, "rcode: %s, ", rcode->name);
} else {
ldns_buffer_printf(output, "rcode: ?? (%u), ", ldns_pkt_get_rcode(pkt));
}
ldns_buffer_printf(output, "id: %d\n", ldns_pkt_id(pkt));
ldns_buffer_printf(output, ";; flags: ");
if (ldns_pkt_qr(pkt)) {
ldns_buffer_printf(output, "qr ");
}
if (ldns_pkt_aa(pkt)) {
ldns_buffer_printf(output, "aa ");
}
if (ldns_pkt_tc(pkt)) {
ldns_buffer_printf(output, "tc ");
}
if (ldns_pkt_rd(pkt)) {
ldns_buffer_printf(output, "rd ");
}
if (ldns_pkt_cd(pkt)) {
ldns_buffer_printf(output, "cd ");
}
if (ldns_pkt_ra(pkt)) {
ldns_buffer_printf(output, "ra ");
}
if (ldns_pkt_ad(pkt)) {
ldns_buffer_printf(output, "ad ");
}
ldns_buffer_printf(output, "; ");
ldns_buffer_printf(output, "QUERY: %u, ", ldns_pkt_qdcount(pkt));
ldns_buffer_printf(output, "ANSWER: %u, ", ldns_pkt_ancount(pkt));
ldns_buffer_printf(output, "AUTHORITY: %u, ", ldns_pkt_nscount(pkt));
ldns_buffer_printf(output, "ADDITIONAL: %u ", ldns_pkt_arcount(pkt));
return ldns_buffer_status(output);
}
ldns_status
ldns_pkt2buffer_str_fmt(ldns_buffer *output,
const ldns_output_format *fmt, const ldns_pkt *pkt)
{
uint16_t i;
ldns_status status = LDNS_STATUS_OK;
char *tmp;
struct timeval time;
time_t time_tt;
if (!pkt) {
ldns_buffer_printf(output, "null");
return LDNS_STATUS_OK;
}
if (ldns_buffer_status_ok(output)) {
status = ldns_pktheader2buffer_str(output, pkt);
if (status != LDNS_STATUS_OK) {
return status;
}
ldns_buffer_printf(output, "\n");
ldns_buffer_printf(output, ";; QUESTION SECTION:\n;; ");
for (i = 0; i < ldns_pkt_qdcount(pkt); i++) {
status = ldns_rr2buffer_str_fmt(output, fmt,
ldns_rr_list_rr(
ldns_pkt_question(pkt), i));
if (status != LDNS_STATUS_OK) {
return status;
}
}
ldns_buffer_printf(output, "\n");
ldns_buffer_printf(output, ";; ANSWER SECTION:\n");
for (i = 0; i < ldns_pkt_ancount(pkt); i++) {
status = ldns_rr2buffer_str_fmt(output, fmt,
ldns_rr_list_rr(
ldns_pkt_answer(pkt), i));
if (status != LDNS_STATUS_OK) {
return status;
}
}
ldns_buffer_printf(output, "\n");
ldns_buffer_printf(output, ";; AUTHORITY SECTION:\n");
for (i = 0; i < ldns_pkt_nscount(pkt); i++) {
status = ldns_rr2buffer_str_fmt(output, fmt,
ldns_rr_list_rr(
ldns_pkt_authority(pkt), i));
if (status != LDNS_STATUS_OK) {
return status;
}
}
ldns_buffer_printf(output, "\n");
ldns_buffer_printf(output, ";; ADDITIONAL SECTION:\n");
for (i = 0; i < ldns_pkt_arcount(pkt); i++) {
status = ldns_rr2buffer_str_fmt(output, fmt,
ldns_rr_list_rr(
ldns_pkt_additional(pkt), i));
if (status != LDNS_STATUS_OK) {
return status;
}
}
ldns_buffer_printf(output, "\n");
/* add some futher fields */
ldns_buffer_printf(output, ";; Query time: %d msec\n",
ldns_pkt_querytime(pkt));
if (ldns_pkt_edns(pkt)) {
ldns_buffer_printf(output,
";; EDNS: version %u; flags:",
ldns_pkt_edns_version(pkt));
if (ldns_pkt_edns_do(pkt)) {
ldns_buffer_printf(output, " do");
}
/* the extended rcode is the value set, shifted four bits,
* and or'd with the original rcode */
if (ldns_pkt_edns_extended_rcode(pkt)) {
ldns_buffer_printf(output, " ; ext-rcode: %d",
(ldns_pkt_edns_extended_rcode(pkt) << 4 | ldns_pkt_get_rcode(pkt)));
}
ldns_buffer_printf(output, " ; udp: %u\n",
ldns_pkt_edns_udp_size(pkt));
if (ldns_pkt_edns_data(pkt)) {
ldns_buffer_printf(output, ";; Data: ");
(void)ldns_rdf2buffer_str(output,
ldns_pkt_edns_data(pkt));
ldns_buffer_printf(output, "\n");
}
}
if (ldns_pkt_tsig(pkt)) {
ldns_buffer_printf(output, ";; TSIG:\n;; ");
(void) ldns_rr2buffer_str_fmt(
output, fmt, ldns_pkt_tsig(pkt));
ldns_buffer_printf(output, "\n");
}
if (ldns_pkt_answerfrom(pkt)) {
tmp = ldns_rdf2str(ldns_pkt_answerfrom(pkt));
ldns_buffer_printf(output, ";; SERVER: %s\n", tmp);
LDNS_FREE(tmp);
}
time = ldns_pkt_timestamp(pkt);
time_tt = (time_t)time.tv_sec;
ldns_buffer_printf(output, ";; WHEN: %s",
(char*)ctime(&time_tt));
ldns_buffer_printf(output, ";; MSG SIZE rcvd: %d\n",
(int)ldns_pkt_size(pkt));
} else {
return ldns_buffer_status(output);
}
return status;
}
ldns_status
ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt)
{
return ldns_pkt2buffer_str_fmt(output, ldns_output_format_default, pkt);
}
#ifdef HAVE_SSL
static ldns_status
ldns_hmac_key2buffer_str(ldns_buffer *output, const ldns_key *k)
{
ldns_status status;
size_t i;
ldns_rdf *b64_bignum;
ldns_buffer_printf(output, "Key: ");
i = ldns_key_hmac_size(k);
b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, ldns_key_hmac_key(k));
status = ldns_rdf2buffer_str(output, b64_bignum);
ldns_rdf_deep_free(b64_bignum);
ldns_buffer_printf(output, "\n");
return status;
}
#endif
#if defined(HAVE_SSL) && defined(USE_GOST)
static ldns_status
ldns_gost_key2buffer_str(ldns_buffer *output, EVP_PKEY *p)
{
unsigned char* pp = NULL;
int ret;
ldns_rdf *b64_bignum;
ldns_status status;
ldns_buffer_printf(output, "GostAsn1: ");
ret = i2d_PrivateKey(p, &pp);
b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, (size_t)ret, pp);
status = ldns_rdf2buffer_str(output, b64_bignum);
ldns_rdf_deep_free(b64_bignum);
OPENSSL_free(pp);
ldns_buffer_printf(output, "\n");
return status;
}
#endif
/** print one b64 encoded bignum to a line in the keybuffer */
static int
ldns_print_bignum_b64_line(ldns_buffer* output, const char* label, const BIGNUM* num)
{
unsigned char *bignumbuf = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
if(!bignumbuf) return 0;
ldns_buffer_printf(output, "%s: ", label);
if(num) {
ldns_rdf *b64_bignum = NULL;
int i = BN_bn2bin(num, bignumbuf);
if (i > LDNS_MAX_KEYLEN) {
LDNS_FREE(bignumbuf);
return 0;
}
b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, (size_t)i, bignumbuf);
if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
ldns_rdf_deep_free(b64_bignum);
LDNS_FREE(bignumbuf);
return 0;
}
ldns_rdf_deep_free(b64_bignum);
ldns_buffer_printf(output, "\n");
} else {
ldns_buffer_printf(output, "(Not available)\n");
}
LDNS_FREE(bignumbuf);
return 1;
}
ldns_status
ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
{
ldns_status status = LDNS_STATUS_OK;
unsigned char *bignum;
#ifdef HAVE_SSL
RSA *rsa;
DSA *dsa;
#endif /* HAVE_SSL */
if (!k) {
return LDNS_STATUS_ERR;
}
bignum = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
if (!bignum) {
return LDNS_STATUS_ERR;
}
if (ldns_buffer_status_ok(output)) {
#ifdef HAVE_SSL
switch(ldns_key_algorithm(k)) {
case LDNS_SIGN_RSASHA1:
case LDNS_SIGN_RSASHA1_NSEC3:
case LDNS_SIGN_RSASHA256:
case LDNS_SIGN_RSASHA512:
case LDNS_SIGN_RSAMD5:
/* copied by looking at dnssec-keygen output */
/* header */
rsa = ldns_key_rsa_key(k);
ldns_buffer_printf(output,"Private-key-format: v1.2\n");
switch(ldns_key_algorithm(k)) {
case LDNS_SIGN_RSAMD5:
ldns_buffer_printf(output,
"Algorithm: %u (RSA)\n",
LDNS_RSAMD5);
break;
case LDNS_SIGN_RSASHA1:
ldns_buffer_printf(output,
"Algorithm: %u (RSASHA1)\n",
LDNS_RSASHA1);
break;
case LDNS_SIGN_RSASHA1_NSEC3:
ldns_buffer_printf(output,
"Algorithm: %u (RSASHA1_NSEC3)\n",
LDNS_RSASHA1_NSEC3);
break;
#ifdef USE_SHA2
case LDNS_SIGN_RSASHA256:
ldns_buffer_printf(output,
"Algorithm: %u (RSASHA256)\n",
LDNS_RSASHA256);
break;
case LDNS_SIGN_RSASHA512:
ldns_buffer_printf(output,
"Algorithm: %u (RSASHA512)\n",
LDNS_RSASHA512);
break;
#endif
default:
#ifdef STDERR_MSGS
fprintf(stderr, "Warning: unknown signature ");
fprintf(stderr,
"algorithm type %u\n",
ldns_key_algorithm(k));
#endif
ldns_buffer_printf(output,
"Algorithm: %u (Unknown)\n",
ldns_key_algorithm(k));
break;
}
/* print to buf, convert to bin, convert to b64,
* print to buf */
#ifndef S_SPLINT_S
if(1) {
const BIGNUM *n=NULL, *e=NULL, *d=NULL,
*p=NULL, *q=NULL, *dmp1=NULL,
*dmq1=NULL, *iqmp=NULL;
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
n = rsa->n;
e = rsa->e;
d = rsa->d;
p = rsa->p;
q = rsa->q;
dmp1 = rsa->dmp1;
dmq1 = rsa->dmq1;
iqmp = rsa->iqmp;
#else
RSA_get0_key(rsa, &n, &e, &d);
RSA_get0_factors(rsa, &p, &q);
RSA_get0_crt_params(rsa, &dmp1,
&dmq1, &iqmp);
#endif
if(!ldns_print_bignum_b64_line(output, "Modulus", n))
goto error;
if(!ldns_print_bignum_b64_line(output, "PublicExponent", e))
goto error;
if(!ldns_print_bignum_b64_line(output, "PrivateExponent", d))
goto error;
if(!ldns_print_bignum_b64_line(output, "Prime1", p))
goto error;
if(!ldns_print_bignum_b64_line(output, "Prime2", q))
goto error;
if(!ldns_print_bignum_b64_line(output, "Exponent1", dmp1))
goto error;
if(!ldns_print_bignum_b64_line(output, "Exponent2", dmq1))
goto error;
if(!ldns_print_bignum_b64_line(output, "Coefficient", iqmp))
goto error;
}
#endif /* splint */
RSA_free(rsa);
break;
case LDNS_SIGN_DSA:
case LDNS_SIGN_DSA_NSEC3:
dsa = ldns_key_dsa_key(k);
ldns_buffer_printf(output,"Private-key-format: v1.2\n");
if (ldns_key_algorithm(k) == LDNS_SIGN_DSA) {
ldns_buffer_printf(output,"Algorithm: 3 (DSA)\n");
} else if (ldns_key_algorithm(k) == LDNS_SIGN_DSA_NSEC3) {
ldns_buffer_printf(output,"Algorithm: 6 (DSA_NSEC3)\n");
}
/* print to buf, convert to bin, convert to b64,
* print to buf */
if(1) {
const BIGNUM *p=NULL, *q=NULL, *g=NULL,
*priv_key=NULL, *pub_key=NULL;
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
#ifndef S_SPLINT_S
p = dsa->p;
q = dsa->q;
g = dsa->g;
priv_key = dsa->priv_key;
pub_key = dsa->pub_key;
#endif /* splint */
#else
DSA_get0_pqg(dsa, &p, &q, &g);
DSA_get0_key(dsa, &pub_key, &priv_key);
#endif
if(!ldns_print_bignum_b64_line(output, "Prime(p)", p))
goto error;
if(!ldns_print_bignum_b64_line(output, "Subprime(q)", q))
goto error;
if(!ldns_print_bignum_b64_line(output, "Base(g)", g))
goto error;
if(!ldns_print_bignum_b64_line(output, "Private_value(x)", priv_key))
goto error;
if(!ldns_print_bignum_b64_line(output, "Public_value(y)", pub_key))
goto error;
}
break;
case LDNS_SIGN_ECC_GOST:
/* no format defined, use blob */
#if defined(HAVE_SSL) && defined(USE_GOST)
ldns_buffer_printf(output, "Private-key-format: v1.2\n");
ldns_buffer_printf(output, "Algorithm: %d (ECC-GOST)\n", LDNS_SIGN_ECC_GOST);
status = ldns_gost_key2buffer_str(output,
#ifndef S_SPLINT_S
k->_key.key
#else
NULL
#endif
);
#else
goto error;
#endif /* GOST */
break;
case LDNS_SIGN_ECDSAP256SHA256:
case LDNS_SIGN_ECDSAP384SHA384:
#ifdef USE_ECDSA
ldns_buffer_printf(output, "Private-key-format: v1.2\n");
ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
#ifndef S_SPLINT_S
ldns_buffer_printf(output, ")\n");
if(k->_key.key) {
EC_KEY* ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
const BIGNUM* b = EC_KEY_get0_private_key(ec);
if(!ldns_print_bignum_b64_line(output, "PrivateKey", b))
goto error;
/* down reference count in EC_KEY
* its still assigned to the PKEY */
EC_KEY_free(ec);
}
#endif /* splint */
#else
goto error;
#endif /* ECDSA */
break;
#ifdef USE_ED25519
case LDNS_SIGN_ED25519:
ldns_buffer_printf(output, "Private-key-format: v1.2\n");
ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
ldns_buffer_printf(output, ")\n");
if(k->_key.key) {
EC_KEY* ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
const BIGNUM* b = EC_KEY_get0_private_key(ec);
if(!ldns_print_bignum_b64_line(output, "PrivateKey", b))
goto error;
/* down reference count in EC_KEY
* its still assigned to the PKEY */
EC_KEY_free(ec);
}
ldns_buffer_printf(output, "\n");
break;
#endif /* USE_ED25519 */
#ifdef USE_ED448
case LDNS_SIGN_ED448:
ldns_buffer_printf(output, "Private-key-format: v1.2\n");
ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
ldns_buffer_printf(output, ")\n");
if(k->_key.key) {
EC_KEY* ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
const BIGNUM* b = EC_KEY_get0_private_key(ec);
if(!ldns_print_bignum_b64_line(output, "PrivateKey", b))
goto error;
/* down reference count in EC_KEY
* its still assigned to the PKEY */
EC_KEY_free(ec);
}
ldns_buffer_printf(output, "\n");
break;
#endif /* USE_ED448 */
case LDNS_SIGN_HMACMD5:
/* there's not much of a format defined for TSIG */
/* It's just a binary blob, Same for all algorithms */
ldns_buffer_printf(output, "Private-key-format: v1.2\n");
ldns_buffer_printf(output, "Algorithm: 157 (HMAC_MD5)\n");
status = ldns_hmac_key2buffer_str(output, k);
break;
case LDNS_SIGN_HMACSHA1:
ldns_buffer_printf(output, "Private-key-format: v1.2\n");
ldns_buffer_printf(output, "Algorithm: 158 (HMAC_SHA1)\n");
status = ldns_hmac_key2buffer_str(output, k);
break;
case LDNS_SIGN_HMACSHA224:
ldns_buffer_printf(output, "Private-key-format: v1.2\n");
ldns_buffer_printf(output, "Algorithm: 162 (HMAC_SHA224)\n");
status = ldns_hmac_key2buffer_str(output, k);
break;
case LDNS_SIGN_HMACSHA256:
ldns_buffer_printf(output, "Private-key-format: v1.2\n");
ldns_buffer_printf(output, "Algorithm: 159 (HMAC_SHA256)\n");
status = ldns_hmac_key2buffer_str(output, k);
break;
case LDNS_SIGN_HMACSHA384:
ldns_buffer_printf(output, "Private-key-format: v1.2\n");
ldns_buffer_printf(output, "Algorithm: 164 (HMAC_SHA384)\n");
status = ldns_hmac_key2buffer_str(output, k);
break;
case LDNS_SIGN_HMACSHA512:
ldns_buffer_printf(output, "Private-key-format: v1.2\n");
ldns_buffer_printf(output, "Algorithm: 165 (HMAC_SHA512)\n");
status = ldns_hmac_key2buffer_str(output, k);
break;
}
#endif /* HAVE_SSL */
} else {
LDNS_FREE(bignum);
return ldns_buffer_status(output);
}
LDNS_FREE(bignum);
return status;
#ifdef HAVE_SSL
/* compiles warn the label isn't used */
error:
LDNS_FREE(bignum);
return LDNS_STATUS_ERR;
#endif /* HAVE_SSL */
}
/*
* Zero terminate the buffer and copy data.
*/
char *
ldns_buffer2str(ldns_buffer *buffer)
{
char *str;
/* check if buffer ends with \0, if not, and
if there is space, add it */
if (*(ldns_buffer_at(buffer, ldns_buffer_position(buffer))) != 0) {
if (!ldns_buffer_reserve(buffer, 1)) {
return NULL;
}
ldns_buffer_write_u8(buffer, (uint8_t) '\0');
if (!ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer))) {
return NULL;
}
}
str = strdup((const char *)ldns_buffer_begin(buffer));
if(!str) {
return NULL;
}
return str;
}
/*
* Zero terminate the buffer and export data.
*/
char *
ldns_buffer_export2str(ldns_buffer *buffer)
{
/* Append '\0' as string terminator */
if (! ldns_buffer_reserve(buffer, 1)) {
return NULL;
}
ldns_buffer_write_u8(buffer, 0);
/* reallocate memory to the size of the string and export */
ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer));
return ldns_buffer_export(buffer);
}
char *
ldns_rdf2str(const ldns_rdf *rdf)
{
char *result = NULL;
ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
if (!tmp_buffer) {
return NULL;
}
if (ldns_rdf2buffer_str(tmp_buffer, rdf) == LDNS_STATUS_OK) {
/* export and return string, destroy rest */
result = ldns_buffer_export2str(tmp_buffer);
}
ldns_buffer_free(tmp_buffer);
return result;
}
char *
ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr)
{
char *result = NULL;
ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
if (!tmp_buffer) {
return NULL;
}
if (ldns_rr2buffer_str_fmt(tmp_buffer, fmt, rr)
== LDNS_STATUS_OK) {
/* export and return string, destroy rest */
result = ldns_buffer_export2str(tmp_buffer);
}
ldns_buffer_free(tmp_buffer);
return result;
}
char *
ldns_rr2str(const ldns_rr *rr)
{
return ldns_rr2str_fmt(ldns_output_format_default, rr);
}
char *
ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt)
{
char *result = NULL;
ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
if (!tmp_buffer) {
return NULL;
}
if (ldns_pkt2buffer_str_fmt(tmp_buffer, fmt, pkt)
== LDNS_STATUS_OK) {
/* export and return string, destroy rest */
result = ldns_buffer_export2str(tmp_buffer);
}
ldns_buffer_free(tmp_buffer);
return result;
}
char *
ldns_pkt2str(const ldns_pkt *pkt)
{
return ldns_pkt2str_fmt(ldns_output_format_default, pkt);
}
char *
ldns_key2str(const ldns_key *k)
{
char *result = NULL;
ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
if (!tmp_buffer) {
return NULL;
}
if (ldns_key2buffer_str(tmp_buffer, k) == LDNS_STATUS_OK) {
/* export and return string, destroy rest */
result = ldns_buffer_export2str(tmp_buffer);
}
ldns_buffer_free(tmp_buffer);
return result;
}
char *
ldns_rr_list2str_fmt(const ldns_output_format *fmt, const ldns_rr_list *list)
{
char *result = NULL;
ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
if (!tmp_buffer) {
return NULL;
}
if (list) {
if (ldns_rr_list2buffer_str_fmt(
tmp_buffer, fmt, list)
== LDNS_STATUS_OK) {
}
} else {
if (fmt == NULL) {
fmt = ldns_output_format_default;
}
if (fmt->flags & LDNS_COMMENT_NULLS) {
ldns_buffer_printf(tmp_buffer, "; (null)\n");
}
}
/* export and return string, destroy rest */
result = ldns_buffer_export2str(tmp_buffer);
ldns_buffer_free(tmp_buffer);
return result;
}
char *
ldns_rr_list2str(const ldns_rr_list *list)
{
return ldns_rr_list2str_fmt(ldns_output_format_default, list);
}
void
ldns_rdf_print(FILE *output, const ldns_rdf *rdf)
{
char *str = ldns_rdf2str(rdf);
if (str) {
fprintf(output, "%s", str);
} else {
fprintf(output, ";Unable to convert rdf to string\n");
}
LDNS_FREE(str);
}
void
ldns_rr_print_fmt(FILE *output,
const ldns_output_format *fmt, const ldns_rr *rr)
{
char *str = ldns_rr2str_fmt(fmt, rr);
if (str) {
fprintf(output, "%s", str);
} else {
fprintf(output, ";Unable to convert rr to string\n");
}
LDNS_FREE(str);
}
void
ldns_rr_print(FILE *output, const ldns_rr *rr)
{
ldns_rr_print_fmt(output, ldns_output_format_default, rr);
}
void
ldns_pkt_print_fmt(FILE *output,
const ldns_output_format *fmt, const ldns_pkt *pkt)
{
char *str = ldns_pkt2str_fmt(fmt, pkt);
if (str) {
fprintf(output, "%s", str);
} else {
fprintf(output, ";Unable to convert packet to string\n");
}
LDNS_FREE(str);
}
void
ldns_pkt_print(FILE *output, const ldns_pkt *pkt)
{
ldns_pkt_print_fmt(output, ldns_output_format_default, pkt);
}
void
ldns_rr_list_print_fmt(FILE *output,
const ldns_output_format *fmt, const ldns_rr_list *lst)
{
size_t i;
for (i = 0; i < ldns_rr_list_rr_count(lst); i++) {
ldns_rr_print_fmt(output, fmt, ldns_rr_list_rr(lst, i));
}
}
void
ldns_rr_list_print(FILE *output, const ldns_rr_list *lst)
{
ldns_rr_list_print_fmt(output, ldns_output_format_default, lst);
}
void
ldns_resolver_print_fmt(FILE *output,
const ldns_output_format *fmt, const ldns_resolver *r)
{
uint16_t i;
ldns_rdf **n;
ldns_rdf **s;
size_t *rtt;
if (!r) {
return;
}
n = ldns_resolver_nameservers(r);
s = ldns_resolver_searchlist(r);
rtt = ldns_resolver_rtt(r);
fprintf(output, "port: %d\n", (int)ldns_resolver_port(r));
fprintf(output, "edns0 size: %d\n", (int)ldns_resolver_edns_udp_size(r));
fprintf(output, "use ip6: %d\n", (int)ldns_resolver_ip6(r));
fprintf(output, "recursive: %d\n", ldns_resolver_recursive(r));
fprintf(output, "usevc: %d\n", ldns_resolver_usevc(r));
fprintf(output, "igntc: %d\n", ldns_resolver_igntc(r));
fprintf(output, "fail: %d\n", ldns_resolver_fail(r));
fprintf(output, "retry: %d\n", (int)ldns_resolver_retry(r));
fprintf(output, "retrans: %d\n", (int)ldns_resolver_retrans(r));
fprintf(output, "fallback: %d\n", ldns_resolver_fallback(r));
fprintf(output, "random: %d\n", ldns_resolver_random(r));
fprintf(output, "timeout: %d\n", (int)ldns_resolver_timeout(r).tv_sec);
fprintf(output, "dnssec: %d\n", ldns_resolver_dnssec(r));
fprintf(output, "dnssec cd: %d\n", ldns_resolver_dnssec_cd(r));
fprintf(output, "trust anchors (%d listed):\n",
(int)ldns_rr_list_rr_count(ldns_resolver_dnssec_anchors(r)));
ldns_rr_list_print_fmt(output, fmt, ldns_resolver_dnssec_anchors(r));
fprintf(output, "tsig: %s %s\n",
ldns_resolver_tsig_keyname(r)?ldns_resolver_tsig_keyname(r):"-",
ldns_resolver_tsig_algorithm(r)?ldns_resolver_tsig_algorithm(r):"-");
fprintf(output, "debug: %d\n", ldns_resolver_debug(r));
fprintf(output, "default domain: ");
ldns_rdf_print(output, ldns_resolver_domain(r));
fprintf(output, "\n");
fprintf(output, "apply default domain: %d\n", ldns_resolver_defnames(r));
fprintf(output, "searchlist (%d listed):\n", (int)ldns_resolver_searchlist_count(r));
for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
fprintf(output, "\t");
ldns_rdf_print(output, s[i]);
fprintf(output, "\n");
}
fprintf(output, "apply search list: %d\n", ldns_resolver_dnsrch(r));
fprintf(output, "nameservers (%d listed):\n", (int)ldns_resolver_nameserver_count(r));
for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
fprintf(output, "\t");
ldns_rdf_print(output, n[i]);
switch ((int)rtt[i]) {
case LDNS_RESOLV_RTT_MIN:
fprintf(output, " - reachable\n");
break;
case LDNS_RESOLV_RTT_INF:
fprintf(output, " - unreachable\n");
break;
}
}
}
void
ldns_resolver_print(FILE *output, const ldns_resolver *r)
{
ldns_resolver_print_fmt(output, ldns_output_format_default, r);
}
void
ldns_zone_print_fmt(FILE *output,
const ldns_output_format *fmt, const ldns_zone *z)
{
if(ldns_zone_soa(z))
ldns_rr_print_fmt(output, fmt, ldns_zone_soa(z));
ldns_rr_list_print_fmt(output, fmt, ldns_zone_rrs(z));
}
void
ldns_zone_print(FILE *output, const ldns_zone *z)
{
ldns_zone_print_fmt(output, ldns_output_format_default, z);
}