summaryrefslogtreecommitdiffstats
path: root/src/dump_cbor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dump_cbor.c')
-rw-r--r--src/dump_cbor.c680
1 files changed, 680 insertions, 0 deletions
diff --git a/src/dump_cbor.c b/src/dump_cbor.c
new file mode 100644
index 0000000..1d2d848
--- /dev/null
+++ b/src/dump_cbor.c
@@ -0,0 +1,680 @@
+/*
+ * Copyright (c) 2016-2021, OARC, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ DNS-in-JSON
+ - generally naming convention
+ - compressedNAME.length is there a point here? isn't the length in the
+ compressed data itself? Maybe have compressedNAME as just the data
+ of the compressed name
+ - 2.5 Additional Message Object Members
+ - IP stuff:
+ - ipProtocol: num
+ - sourceIpAddress: string
+ - sourcePort: num
+ - destinationIpAddress: string
+ - destinationPort: num
+ or
+ - ip: [ ipProtocol, sourceIpAddress, sourcePort, destinationIpAddress, destinationPort ]
+ - dateNanoFractions as addition to dateSeconds, specify the fraction of
+ nano seconds separatly to have better precision.
+*/
+
+#include "config.h"
+
+#include "dump_cbor.h"
+#include "dnscap.h"
+#include "iaddr.h"
+
+#if HAVE_LIBTINYCBOR
+
+#include <ldns/ldns.h>
+#if HAVE_CBOR_CBOR_H
+#include <cbor/cbor.h>
+#endif
+#if HAVE_CBOR_H
+#include <cbor.h>
+#endif
+
+static uint8_t* cbor_buf = 0;
+static size_t cbor_size = 128 * 1024;
+/*static size_t cbor_size = 1024;*/
+static size_t cbor_reserve = 64 * 1024;
+static CborEncoder cbor_root, cbor_pkts;
+/*static cbor_stringref_t *cbor_stringrefs = 0;*/
+/*static size_t cbor_stringref_size = 8192;*/
+static int cbor_flushed = 1;
+
+int cbor_set_size(size_t size)
+{
+ if (!size) {
+ return DUMP_CBOR_EINVAL;
+ }
+
+ cbor_size = size;
+
+ return DUMP_CBOR_OK;
+}
+
+int cbor_set_reserve(size_t reserve)
+{
+ if (!reserve) {
+ return DUMP_CBOR_EINVAL;
+ }
+
+ cbor_reserve = reserve;
+
+ return DUMP_CBOR_OK;
+}
+
+#define append_cbor(func, name, type) \
+ CborError func(CborEncoder* encoder, type value, int* should_flush) \
+ { \
+ CborError err; \
+ uint8_t* ptr = encoder->data.ptr; \
+ err = name(encoder, value); \
+ if (err == CborErrorOutOfMemory && !*should_flush) { \
+ *should_flush = 1; \
+ encoder->data.ptr = ptr; \
+ encoder->end = cbor_buf + cbor_size + cbor_reserve; \
+ err = name(encoder, value); \
+ } \
+ return err; \
+ }
+
+static append_cbor(append_cbor_text_stringz, cbor_encode_text_stringz, const char*);
+static append_cbor(append_cbor_boolean, cbor_encode_boolean, bool);
+static append_cbor(append_cbor_int, cbor_encode_int, int64_t);
+static append_cbor(append_cbor_uint, cbor_encode_uint, uint64_t);
+static append_cbor(append_cbor_double, cbor_encode_double, double);
+
+static CborError append_cbor_bytes(CborEncoder* encoder, uint8_t* bytes, size_t length, int* should_flush)
+{
+ CborError err;
+ uint8_t* ptr = encoder->data.ptr;
+ err = cbor_encode_byte_string(encoder, bytes, length);
+ if (err == CborErrorOutOfMemory && !*should_flush) {
+ *should_flush = 1;
+ encoder->data.ptr = ptr;
+ encoder->end = cbor_buf + cbor_size + cbor_reserve;
+ err = cbor_encode_byte_string(encoder, bytes, length);
+ }
+ return err;
+}
+
+/*CborError append_cbor_text_stringz2(CborEncoder *encoder, const char *value, int *should_flush) {*/
+/* CborError err;*/
+/* uint8_t *ptr = encoder->data.ptr;*/
+/* err = cbor_encode_byte_string(encoder, bytes, length);*/
+/* if (err == CborErrorOutOfMemory && !*should_flush) {*/
+/* *should_flush = 1;*/
+/* encoder->data.ptr = ptr;*/
+/* encoder->end = cbor_buf + cbor_size + cbor_reserve;*/
+/* err = cbor_encode_byte_string(encoder, bytes, length);*/
+/* }*/
+/* return err;*/
+/*}*/
+
+#define append_cbor_container(func, name) \
+ CborError func(CborEncoder* encoder, CborEncoder* container, size_t length, int* should_flush) \
+ { \
+ CborError err; \
+ uint8_t* ptr = encoder->data.ptr; \
+ err = name(encoder, container, length); \
+ if (err == CborErrorOutOfMemory && !*should_flush) { \
+ *should_flush = 1; \
+ encoder->data.ptr = ptr; \
+ encoder->end = cbor_buf + cbor_size + cbor_reserve; \
+ err = name(encoder, container, length); \
+ } \
+ return err; \
+ }
+
+static append_cbor_container(append_cbor_array, cbor_encoder_create_array);
+static append_cbor_container(append_cbor_map, cbor_encoder_create_map);
+
+static CborError close_cbor_container(CborEncoder* encoder, CborEncoder* container, int* should_flush)
+{
+ CborError err;
+ uint8_t* ptr = encoder->data.ptr;
+ err = cbor_encoder_close_container_checked(encoder, container);
+ if (err == CborErrorOutOfMemory && !*should_flush) {
+ *should_flush = 1;
+ encoder->data.ptr = ptr;
+ encoder->end = cbor_buf + cbor_size + cbor_reserve;
+ err = cbor_encoder_close_container_checked(encoder, container);
+ }
+ return err;
+}
+
+static CborError cbor_ldns_rr_list(CborEncoder* encoder, ldns_rr_list* list, size_t count, int* should_flush)
+{
+ CborError cbor_err = CborNoError;
+ size_t n;
+ ldns_buffer* dname;
+ char* dname_str;
+
+ if (!encoder) {
+ return CborErrorInternalError;
+ }
+ if (!list) {
+ return CborErrorInternalError;
+ }
+ if (!count) {
+ return CborErrorInternalError;
+ }
+ if (!should_flush) {
+ return CborErrorInternalError;
+ }
+
+ for (n = 0; cbor_err == CborNoError && n < count; n++) {
+ CborEncoder cbor_rr;
+ uint8_t* rdata_bytes;
+ ldns_buffer* rdata;
+ ldns_rr* rr = ldns_rr_list_rr(list, n);
+ size_t rd_count;
+
+ if (!rr) {
+ return CborErrorInternalError;
+ }
+ rd_count = ldns_rr_rd_count(rr);
+
+ if (!(dname = ldns_buffer_new(512))) {
+ return CborErrorOutOfMemory;
+ }
+ if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) {
+ ldns_buffer_free(dname);
+ return CborErrorInternalError;
+ }
+ ldns_buffer_write_u8(dname, 0);
+ if (!(dname_str = ldns_buffer_export(dname))) {
+ ldns_buffer_free(dname);
+ return CborErrorOutOfMemory;
+ }
+
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_map(encoder, &cbor_rr, CborIndefiniteLength, should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor_rr, "NAME", should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor_rr, dname_str, should_flush);
+ free(dname_str);
+ ldns_buffer_free(dname);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor_rr, "CLASS", should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&cbor_rr, ldns_rr_get_class(rr), should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor_rr, "TYPE", should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&cbor_rr, ldns_rr_get_type(rr), should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor_rr, "TTL", should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&cbor_rr, ldns_rr_ttl(rr), should_flush);
+
+ if (rd_count == 1) {
+ if (!(rdata = ldns_buffer_new(64 * 1024))) {
+ return CborErrorOutOfMemory;
+ }
+ if (ldns_rdf2buffer_wire(rdata, ldns_rr_rdf(rr, 0)) != LDNS_STATUS_OK) {
+ ldns_buffer_free(rdata);
+ return CborErrorInternalError;
+ }
+ if (!(rdata_bytes = ldns_buffer_export(rdata))) {
+ ldns_buffer_free(rdata);
+ return CborErrorOutOfMemory;
+ }
+
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor_rr, "RDLENGTH", should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&cbor_rr, ldns_buffer_position(rdata), should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor_rr, "RDATA", should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_bytes(&cbor_rr, rdata_bytes, ldns_buffer_position(rdata), should_flush);
+ free(rdata_bytes);
+ ldns_buffer_free(rdata);
+ } else if (rd_count > 1) {
+ size_t n2;
+ CborEncoder rr_set;
+
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor_rr, "rrSet", should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_array(&cbor_rr, &rr_set, CborIndefiniteLength, should_flush);
+ for (n2 = 0; n2 < rd_count; n2++) {
+ if (!(rdata = ldns_buffer_new(64 * 1024))) {
+ return CborErrorOutOfMemory;
+ }
+ if (ldns_rdf2buffer_wire(rdata, ldns_rr_rdf(rr, n2)) != LDNS_STATUS_OK) {
+ ldns_buffer_free(rdata);
+ return CborErrorInternalError;
+ }
+ if (!(rdata_bytes = ldns_buffer_export(rdata))) {
+ ldns_buffer_free(rdata);
+ return CborErrorOutOfMemory;
+ }
+
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&rr_set, "RDLENGTH", should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&rr_set, ldns_buffer_position(rdata), should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&rr_set, "RDATA", should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_bytes(&rr_set, rdata_bytes, ldns_buffer_position(rdata), should_flush);
+ free(rdata_bytes);
+ ldns_buffer_free(rdata);
+ }
+ if (cbor_err == CborNoError)
+ cbor_err = close_cbor_container(&cbor_rr, &rr_set, should_flush);
+ }
+
+ if (cbor_err == CborNoError)
+ cbor_err = close_cbor_container(encoder, &cbor_rr, should_flush);
+ }
+
+ return cbor_err;
+}
+
+int output_cbor(iaddr from, iaddr to, uint8_t proto, unsigned flags, unsigned sport, unsigned dport, my_bpftimeval ts, const u_char* payload, size_t payloadlen)
+{
+ ldns_pkt* pkt = 0;
+ ldns_status ldns_rc;
+
+ if (!payload) {
+ return DUMP_CBOR_EINVAL;
+ }
+ if (!payloadlen) {
+ return DUMP_CBOR_EINVAL;
+ }
+
+ /* if (!cbor_stringrefs) {*/
+ /* cbor_stringrefs = calloc(1, cbor_stringref_size);*/
+ /* }*/
+ if (!cbor_buf) {
+ if (!(cbor_buf = calloc(1, cbor_size + cbor_reserve))) {
+ return DUMP_CBOR_ENOMEM;
+ }
+ }
+ if (cbor_flushed) {
+ CborError cbor_err;
+
+ cbor_encoder_init(&cbor_root, cbor_buf, cbor_size, 0);
+ /* cbor_err = cbor_encode_tag(&cbor_root, 256);*/
+ /* if (cbor_err == CborNoError)*/
+ cbor_err = cbor_encoder_create_array(&cbor_root, &cbor_pkts, CborIndefiniteLength);
+ if (cbor_err != CborNoError) {
+ fprintf(stderr, "cbor init error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err));
+ return DUMP_CBOR_ECBOR;
+ }
+ cbor_flushed = 0;
+ }
+
+ ldns_rc = ldns_wire2pkt(&pkt, payload, payloadlen);
+
+ if (ldns_rc != LDNS_STATUS_OK) {
+ fprintf(stderr, "ldns error [%d]: %s\n", ldns_rc, ldns_get_errorstr_by_id(ldns_rc));
+ return DUMP_CBOR_ELDNS;
+ }
+ if (!pkt) {
+ return DUMP_CBOR_ELDNS;
+ }
+
+ CborEncoder cbor, ip;
+ CborError cbor_err = CborNoError;
+ int should_flush = 0;
+
+ cbor_err = append_cbor_map(&cbor_pkts, &cbor, CborIndefiniteLength, &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "dateSeconds", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_double(&cbor, (double)ts.tv_sec + ((double)ts.tv_usec / 1000000), &should_flush);
+ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "dateNanoFractions", &should_flush);*/
+ /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ts.tv_usec * 1000, &should_flush);*/
+
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "ip", &should_flush);
+ /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, proto, &should_flush);*/
+ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "sourceIpAddress", &should_flush);*/
+ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, ia_str(from), &should_flush);*/
+ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "sourcePort", &should_flush);*/
+ /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, sport, &should_flush);*/
+ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "destinationIpAddress", &should_flush);*/
+ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, ia_str(to), &should_flush);*/
+ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "destinationPort", &should_flush);*/
+ /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, dport, &should_flush);*/
+
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_array(&cbor, &ip, CborIndefiniteLength, &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&ip, proto, &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&ip, ia_str(from), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&ip, sport, &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&ip, ia_str(to), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&ip, dport, &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = close_cbor_container(&cbor, &ip, &should_flush);
+
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "ID", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&cbor, ldns_pkt_id(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "QR", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_boolean(&cbor, ldns_pkt_qr(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "Opcode", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&cbor, ldns_pkt_get_opcode(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "AA", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_boolean(&cbor, ldns_pkt_aa(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "TC", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_boolean(&cbor, ldns_pkt_tc(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "RD", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_boolean(&cbor, ldns_pkt_rd(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "RA", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_boolean(&cbor, ldns_pkt_ra(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "AD", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_boolean(&cbor, ldns_pkt_ad(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "CD", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_boolean(&cbor, ldns_pkt_cd(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "RCODE", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&cbor, ldns_pkt_get_rcode(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "QDCOUNT", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&cbor, ldns_pkt_qdcount(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "ANCOUNT", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&cbor, ldns_pkt_ancount(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "NSCOUNT", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&cbor, ldns_pkt_nscount(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "ARCOUNT", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&cbor, ldns_pkt_arcount(pkt), &should_flush);
+
+ /* questionRRs */
+
+ if (ldns_pkt_qdcount(pkt) > 0) {
+ ldns_rr_list* list = ldns_pkt_question(pkt);
+ ldns_rr* rr;
+ size_t n, qdcount = ldns_pkt_qdcount(pkt);
+ ldns_buffer* dname;
+ char* dname_str;
+
+ if (!list) {
+ ldns_pkt_free(pkt);
+ return DUMP_CBOR_ELDNS;
+ }
+ rr = ldns_rr_list_rr(list, 0);
+ if (!rr) {
+ ldns_pkt_free(pkt);
+ return DUMP_CBOR_ELDNS;
+ }
+
+ if (!(dname = ldns_buffer_new(512))) {
+ ldns_pkt_free(pkt);
+ return DUMP_CBOR_ENOMEM;
+ }
+ if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) {
+ ldns_buffer_free(dname);
+ ldns_pkt_free(pkt);
+ return DUMP_CBOR_ELDNS;
+ }
+ ldns_buffer_write_u8(dname, 0);
+ if (!(dname_str = ldns_buffer_export(dname))) {
+ ldns_buffer_free(dname);
+ ldns_pkt_free(pkt);
+ return DUMP_CBOR_ENOMEM;
+ }
+
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "QNAME", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, dname_str, &should_flush);
+ free(dname_str);
+ ldns_buffer_free(dname);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "QCLASS", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&cbor, ldns_rr_get_class(rr), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "QTYPE", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&cbor, ldns_rr_get_type(rr), &should_flush);
+
+ if (qdcount > 1) {
+ CborEncoder queries;
+
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "questionRRs", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_array(&cbor, &queries, CborIndefiniteLength, &should_flush);
+ for (n = 1; cbor_err == CborNoError && n < qdcount; n++) {
+ CborEncoder query;
+
+ rr = ldns_rr_list_rr(list, n);
+ if (!rr) {
+ ldns_pkt_free(pkt);
+ return DUMP_CBOR_ELDNS;
+ }
+
+ if (!(dname = ldns_buffer_new(512))) {
+ ldns_pkt_free(pkt);
+ return DUMP_CBOR_ENOMEM;
+ }
+ if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) {
+ ldns_buffer_free(dname);
+ ldns_pkt_free(pkt);
+ return DUMP_CBOR_ELDNS;
+ }
+ ldns_buffer_write_u8(dname, 0);
+ if (!(dname_str = ldns_buffer_export(dname))) {
+ ldns_buffer_free(dname);
+ ldns_pkt_free(pkt);
+ return DUMP_CBOR_ENOMEM;
+ }
+
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_map(&queries, &query, CborIndefiniteLength, &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&query, "NAME", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&query, dname_str, &should_flush);
+ free(dname_str);
+ ldns_buffer_free(dname);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&query, "CLASS", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&query, ldns_rr_get_class(rr), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&query, "TYPE", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_uint(&query, ldns_rr_get_type(rr), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = close_cbor_container(&queries, &query, &should_flush);
+ }
+ if (cbor_err == CborNoError)
+ cbor_err = close_cbor_container(&cbor, &queries, &should_flush);
+ }
+ }
+
+ /* answerRRs */
+
+ if (ldns_pkt_ancount(pkt) > 0) {
+ CborEncoder cbor_rrs;
+
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "answerRRs", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush);
+ cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_answer(pkt), ldns_pkt_ancount(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush);
+ }
+
+ /* authorityRRs */
+
+ if (ldns_pkt_nscount(pkt) > 0) {
+ CborEncoder cbor_rrs;
+
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "authorityRRs", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush);
+ cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_authority(pkt), ldns_pkt_nscount(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush);
+ }
+
+ /* additionalRRs */
+
+ if (ldns_pkt_arcount(pkt) > 0) {
+ CborEncoder cbor_rrs;
+
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_text_stringz(&cbor, "additionalRRs", &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush);
+ cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_additional(pkt), ldns_pkt_arcount(pkt), &should_flush);
+ if (cbor_err == CborNoError)
+ cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush);
+ }
+
+ ldns_pkt_free(pkt);
+
+ if (cbor_err == CborNoError)
+ cbor_err = close_cbor_container(&cbor_pkts, &cbor, &should_flush);
+
+ if (cbor_err != CborNoError) {
+ fprintf(stderr, "cbor error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err));
+ return DUMP_CBOR_ECBOR;
+ }
+
+ if (should_flush) {
+ if ((cbor_err = cbor_encoder_close_container_checked(&cbor_root, &cbor_pkts)) != CborNoError) {
+ fprintf(stderr, "cbor error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err));
+ return DUMP_CBOR_ECBOR;
+ }
+
+ fprintf(stderr, "cbor output: %lu bytes\n", cbor_encoder_get_buffer_size(&cbor_root, cbor_buf));
+
+ cbor_flushed = 1;
+ return DUMP_CBOR_FLUSH;
+ }
+
+ return DUMP_CBOR_OK;
+}
+
+int dump_cbor(FILE* fp)
+{
+ CborError cbor_err;
+
+ if (!fp) {
+ return DUMP_CBOR_EINVAL;
+ }
+
+ if ((cbor_err = cbor_encoder_close_container_checked(&cbor_root, &cbor_pkts)) != CborNoError) {
+ fprintf(stderr, "cbor error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err));
+ return DUMP_CBOR_ECBOR;
+ }
+
+ fprintf(stderr, "cbor output: %lu bytes\n", cbor_encoder_get_buffer_size(&cbor_root, cbor_buf));
+
+ if (fwrite(cbor_buf, cbor_encoder_get_buffer_size(&cbor_root, cbor_buf), 1, fp) != 1) {
+ return DUMP_CBOR_EWRITE;
+ }
+
+ return DUMP_CBOR_OK;
+}
+
+int have_cbor_support()
+{
+ return 1;
+}
+
+#else /* HAVE_LIBTINYCBOR */
+
+int cbor_set_size(size_t size)
+{
+ return DUMP_CBOR_ENOSUP;
+}
+
+int cbor_set_reserve(size_t reserve)
+{
+ return DUMP_CBOR_ENOSUP;
+}
+
+int output_cbor(iaddr from, iaddr to, uint8_t proto, unsigned flags, unsigned sport, unsigned dport, my_bpftimeval ts, const u_char* payload, size_t payloadlen)
+{
+ return DUMP_CBOR_ENOSUP;
+}
+
+int dump_cbor(FILE* fp)
+{
+ return DUMP_CBOR_ENOSUP;
+}
+
+int have_cbor_support()
+{
+ return 0;
+}
+
+#endif