/duration.o
/error.lo
/error.o
+/edns.lo
+/edns.o
/examples/.libs/
/examples/ldns-chaos
/examples/ldns-chaos.lo
INSTALL = $(srcdir)/install-sh
LIBLOBJS = $(LIBOBJS:.o=.lo)
-LDNS_LOBJS = buffer.lo dane.lo dname.lo dnssec.lo dnssec_sign.lo dnssec_verify.lo dnssec_zone.lo duration.lo error.lo higher.lo host2str.lo host2wire.lo keys.lo net.lo packet.lo parse.lo radix.lo rbtree.lo rdata.lo resolver.lo rr.lo rr_functions.lo sha1.lo sha2.lo str2host.lo tsig.lo update.lo util.lo wire2host.lo zone.lo
+LDNS_LOBJS = buffer.lo dane.lo dname.lo dnssec.lo dnssec_sign.lo dnssec_verify.lo dnssec_zone.lo duration.lo error.lo higher.lo host2str.lo host2wire.lo keys.lo net.lo packet.lo parse.lo radix.lo rbtree.lo rdata.lo resolver.lo rr.lo rr_functions.lo sha1.lo sha2.lo str2host.lo tsig.lo update.lo util.lo wire2host.lo zone.lo edns.lo
LDNS_LOBJS_EX = ^linktest\.c$$
LDNS_ALL_LOBJS = $(LDNS_LOBJS) $(LIBLOBJS)
LIB = libldns.la
-LDNS_HEADERS = buffer.h dane.h dname.h dnssec.h dnssec_sign.h dnssec_verify.h dnssec_zone.h duration.h error.h higher.h host2str.h host2wire.h keys.h ldns.h packet.h parse.h radix.h rbtree.h rdata.h resolver.h rr_functions.h rr.h sha1.h sha2.h str2host.h tsig.h update.h wire2host.h zone.h
+LDNS_HEADERS = buffer.h dane.h dname.h dnssec.h dnssec_sign.h dnssec_verify.h dnssec_zone.h duration.h error.h higher.h host2str.h host2wire.h keys.h ldns.h packet.h parse.h radix.h rbtree.h rdata.h resolver.h rr_functions.h rr.h sha1.h sha2.h str2host.h tsig.h update.h wire2host.h zone.h edns.h
LDNS_HEADERS_EX = ^config\.h|common\.h|util\.h|net\.h$$
LDNS_HEADERS_GEN= common.h util.h net.h
$(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
$(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/radix.h \
$(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h
+edns.lo edns.o: $(srcdir)/edns.c ldns/config.h $(srcdir)/ldns/edns.h
compat/b64_ntop.lo compat/b64_ntop.o: $(srcdir)/compat/b64_ntop.c ldns/config.h
compat/b64_pton.lo compat/b64_pton.o: $(srcdir)/compat/b64_pton.c ldns/config.h
compat/calloc.lo compat/calloc.o: $(srcdir)/compat/calloc.c ldns/config.h
ldns_resolver_set_tsig_algorithm(res, tsig_algorithm);
}
+ printf("HERE: drill:main() PURPOSE: %d\n", PURPOSE);
+
/* main switching part of drill */
switch(PURPOSE) {
case DRILL_TRACE:
--- /dev/null
+/*
+ * edns.c
+ *
+ * edns implementation
+ *
+ * a Net::DNS like library for C
+ *
+ * (c) NLnet Labs, 2004-2022
+ *
+ * See the file LICENSE for the license
+ */
+
+#include <ldns/ldns.h>
+
+/*
+ * Access functions
+ * functions to get and set type checking
+ */
+
+/* read */
+size_t
+ldns_edns_get_size(const ldns_edns_option *edns)
+{
+ assert(edns != NULL);
+ return edns->_size;
+}
+
+ldns_edns_option_code
+ldns_edns_get_code(const ldns_edns_option *edns)
+{
+ assert(edns != NULL);
+ return edns->_code;
+}
+
+uint8_t *
+ldns_edns_get_data(const ldns_edns_option *edns)
+{
+ assert(edns != NULL);
+ return edns->_data;
+}
+
+
+/* write */
+void
+ldns_edns_set_size(ldns_edns_option *edns, size_t size)
+{
+ assert(edns != NULL);
+ edns->_size = size;
+}
+
+void
+ldns_edns_set_code(ldns_edns_option *edns, ldns_edns_option_code code)
+{
+ assert(edns != NULL);
+ edns->_code = code;
+}
+
+void
+ldns_edns_set_data(ldns_edns_option *edns, void *data)
+{
+ /* only copy the pointer */
+ assert(edns != NULL);
+ edns->_data = data;
+}
+
+/* note: data must be allocated memory */
+ldns_edns_option *
+ldns_edns_new(ldns_edns_option_code code, size_t size, void *data)
+{
+ ldns_edns_option *edns;
+ edns = LDNS_MALLOC(ldns_edns_option);
+ if (!edns) {
+ return NULL;
+ }
+ ldns_edns_set_size(edns, size);
+ ldns_edns_set_code(edns, code);
+ ldns_edns_set_data(edns, data);
+ return edns;
+}
+
+void
+ldns_edns_deep_free(ldns_edns_option *edns)
+{
+ if (edns) {
+ if (edns->_data) {
+ LDNS_FREE(edns->_data);
+ }
+ LDNS_FREE(edns);
+ }
+}
+
+void
+ldns_edns_free(ldns_edns_option *edns)
+{
+ if (edns) {
+ LDNS_FREE(edns);
+ }
+}
if (ldns_pkt_edns_data(pkt)) {
ldns_buffer_printf(output, ";; Data: ");
+
+ // @TODO loop through options on the newly created ldns_edns_opt
+ // struct and create
+
(void)ldns_rdf2buffer_str(output,
ldns_pkt_edns_data(pkt));
ldns_buffer_printf(output, "\n");
--- /dev/null
+/*
+ * edns.h
+ *
+ *
+ * a Net::DNS like library for C
+ *
+ * (c) NLnet Labs, 2004-2022
+ *
+ * See the file LICENSE for the license
+ */
+
+#ifndef LDNS_EDNS_H
+#define LDNS_EDNS_H
+
+#include <ldns/common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+/**
+ * EDNS option codes
+ */
+enum ldns_enum_edns_option
+{
+ LDNS_EDNS_LLQ = 1, /* http://files.dns-sd.org/draft-sekar-dns-llq.txt */
+ LDNS_EDNS_UL = 2, /* http://files.dns-sd.org/draft-sekar-dns-ul.txt */
+ LDNS_EDNS_NSID = 3, /* RFC5001 */
+ /* 4 draft-cheshire-edns0-owner-option */
+ LDNS_EDNS_DAU = 5, /* RFC6975 */
+ LDNS_EDNS_DHU = 6, /* RFC6975 */
+ LDNS_EDNS_N3U = 7, /* RFC6975 */
+ LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */
+ LDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/
+ LDNS_EDNS_PADDING = 12, /* RFC7830 */
+ LDNS_EDNS_EDE = 15, /* RFC8914 */
+ LDNS_EDNS_CLIENT_TAG = 16 /* draft-bellis-dnsop-edns-tags-01 */
+};
+typedef enum ldns_enum_edns_option ldns_edns_option_code;
+
+/**
+ *
+ * An EDNS option is structed as follows:
+ +0 (MSB) +1 (LSB)
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ 0: | OPTION-CODE |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ 2: | OPTION-LENGTH |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ 4: | |
+ / OPTION-DATA /
+ / /
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ *
+ *
+ * @TODO write this
+ */
+struct ldns_struct_edns_option {
+ ldns_edns_option_code _code;
+ size_t _size;
+ void *_data;
+};
+typedef struct ldns_struct_edns_option ldns_edns_option;
+
+
+/*
+ *
+ * @TODO write this
+ */
+struct ldns_struct_edns_option_list
+{
+ size_t _option_count;
+ size_t _rr_capacity; // ???
+ ldns_rr **_options;
+};
+typedef struct ldns_struct_edns_option_list edns_option_list;
+
+/*
+ * Access functions
+ * do this as functions to get type checking
+ */
+
+/**
+ * returns the size of the EDNS data.
+ * \param[in] *edns the EDNS struct to read from
+ * \return uint16_t with the size
+ */
+size_t ldns_edns_get_size(const ldns_edns_option *edns);
+
+/**
+ * returns the size of the EDNS data.
+ * \param[in] *edns the EDNS struct to read from
+ * \return uint16_t with the size
+ */
+ldns_edns_option_code ldns_edns_get_code(const ldns_edns_option *edns);
+
+/**
+ * returns the EDNS option data.
+ * \param[in] *edns the rdf to read from
+ * \return uint8_t* pointer to the rdf's data
+ */
+uint8_t *ldns_edns_get_data(const ldns_edns_option *edns);
+
+
+/**
+ * allocates a new EDNS structure and fills it.
+ * This function DOES NOT copy the contents from
+ * the buffer, unlike ldns_rdf_new_frm_data()
+ * \param[in] type type of the rdf
+ * \param[in] size size of the buffer
+ * \param[in] data pointer to the buffer to be copied
+ * \return the new rdf structure or NULL on failure
+ */
+ldns_edns_option *ldns_edns_new(ldns_edns_option_code code, size_t size, void *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LDNS_EDNS_H */
\ No newline at end of file
#include <ldns/rbtree.h>
#include <ldns/sha1.h>
#include <ldns/sha2.h>
+#include <ldns/edns.h>
#ifdef __cplusplus
extern "C" {
#include <ldns/common.h>
#include <ldns/rr.h>
#include <sys/time.h>
+#include <ldns/edns.h>
#ifdef __cplusplus
extern "C" {
uint16_t _edns_z;
/** Arbitrary EDNS rdata */
ldns_rdf *_edns_data;
+
+ /** Structured ENDS options */
+ ldns_edns_option *_edns_options; // @TODO rewrite into "edns_option_list" struct
+
/** Question section */
ldns_rr_list *_question;
/** Answer section */
void ldns_pkt_set_edns_unassigned(ldns_pkt *packet, uint16_t value);
/**
- * returns true if this packet needs and EDNS rr to be sent.
+ * returns true if this packet needs an EDNS rr to be sent.
* At the moment the only reason is an expected packet
* size larger than 512 bytes, but for instance dnssec would
* be a good reason too.
*/
void ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data);
+
+// *
+// * Set the packet's edns data
+// * \param[in] packet the packet
+// * \param[in] data the data
+// * \return 0 is there is no next EDNS option in the
+
+// uint16_t ldns_pkt_get_next_edns_option(ldns_pkt *packet, );
+
+
+
+
/**
* allocates and initializes a ldns_pkt structure.
* \return pointer to the new packet
LDNS_RR_TYPE_DNAME = 39,
/** dnsind-kitchen-sink-02.txt */
LDNS_RR_TYPE_SINK = 40,
- /** Pseudo OPT record... */
+ /** OPT record RFC 6891 */
LDNS_RR_TYPE_OPT = 41,
/** RFC3123 */
LDNS_RR_TYPE_APL = 42,
ldns_pkt_set_edns_data(packet, NULL);
packet->_edns_present = false;
+ packet->_edns_options = NULL; //@TODO change this to set_function/list function
+
ldns_pkt_set_tsig(packet, NULL);
return packet;
end = *pos + (size_t) rd_length;
rdf_index = 0;
- while (*pos < end &&
+ while (*pos < end &&
rdf_index < ldns_rr_descriptor_maximum(descriptor)) {
cur_rdf_length = 0;
}
+
+/* Parse the additional section like wire2rr with a case for EDNS options */
+// @TODO remove static?
+static ldns_status
+ldns_wire2rr_additional(ldns_pkt* packet, ldns_rr **rr_p, const uint8_t *wire,
+ size_t max, size_t *pos)
+{
+ size_t end;
+ ldns_rdf *owner = NULL;
+ ldns_rr *rr = ldns_rr_new();
+ ldns_status status;
+ ldns_rr_type rr_type;
+ uint16_t rd_length;
+
+ status = ldns_wire2dname(&owner, wire, max, pos);
+ LDNS_STATUS_CHECK_GOTO(status, status_error);
+
+ ldns_rr_set_owner(rr, owner);
+
+ if (*pos + 4 > max) {
+ status = LDNS_STATUS_PACKET_OVERFLOW;
+ goto status_error;
+ }
+
+ rr_type = ldns_read_uint16(&wire[*pos]);
+ ldns_rr_set_type(rr, rr_type);
+ *pos = *pos + 2;
+
+ ldns_rr_set_class(rr, ldns_read_uint16(&wire[*pos]));
+ *pos = *pos + 2;
+
+ if (*pos + 4 > max) {
+ status = LDNS_STATUS_PACKET_OVERFLOW;
+ goto status_error;
+ }
+ ldns_rr_set_ttl(rr, ldns_read_uint32(&wire[*pos]));
+
+ *pos = *pos + 4;
+
+ if (rr_type != LDNS_RR_TYPE_OPT)
+ status = ldns_wire2rdf(rr, wire, max, pos);
+ else {
+ ldns_edns_option* edns;
+ ldns_edns_option_code option_code;
+ uint16_t option_size;
+ uint8_t *option_data;
+
+ if (*pos + 2 > max) {
+ status = LDNS_STATUS_PACKET_OVERFLOW;
+ goto status_error;
+ }
+
+ rd_length = ldns_read_uint16(&wire[*pos]);
+ *pos = *pos + 2;
+
+ if (*pos + rd_length > max) {
+ status = LDNS_STATUS_PACKET_OVERFLOW;
+ goto status_error;
+ }
+
+ end = *pos + (size_t) rd_length;
+
+ while (*pos < end) { // @TODO fix for multiple EDNS opts?
+ option_code = ldns_read_uint16(&wire[*pos]);
+ option_size = ldns_read_uint16(&wire[*pos + 2]);
+ *pos = *pos + 4;
+
+ option_data = LDNS_XMALLOC(uint8_t, option_size);
+ if (!option_data) {
+ status = LDNS_STATUS_MEM_ERR;
+ goto status_error;
+ }
+ memcpy(option_data, &wire[*pos], option_size);
+
+ printf("HERE: ldns_wire2rr_additional():option code: %d\n", option_code);
+ printf("HERE: ldns_wire2rr_additional():option size: %d\n", option_size);
+
+ edns = ldns_edns_new(option_code, option_size, option_data);
+
+ // @TODO push edns to packet/rr list (1) with function (2)
+ packet->_edns_options = edns;
+
+ *pos = *pos + option_size;
+ }
+
+ }
+
+ LDNS_STATUS_CHECK_GOTO(status, status_error);
+ ldns_rr_set_question(rr, false);
+
+ *rr_p = rr;
+ return LDNS_STATUS_OK;
+
+status_error:
+ ldns_rr_free(rr);
+ return status;
+}
+
/* TODO:
can *pos be incremented at READ_INT? or maybe use something like
RR_CLASS(wire)?
ldns_pkt *packet = ldns_pkt_new();
ldns_status status = LDNS_STATUS_OK;
uint8_t have_edns = 0;
+ // ldns_rdf *edns;
+ ldns_edns_option *edns;
uint8_t data[4];
return LDNS_STATUS_MEM_ERR;
}
+ printf("HERE: ldns_wire2pkt()\n");
+
status = ldns_wire2pkt_hdr(packet, wire, max, &pos);
LDNS_STATUS_CHECK_GOTO(status, status_error);
}
}
for (i = 0; i < ldns_pkt_arcount(packet); i++) {
- status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_ADDITIONAL);
+
+ status = ldns_wire2rr_additional(packet ,&rr, wire, max, &pos);
+
+ // status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_ADDITIONAL);
if (status == LDNS_STATUS_PACKET_OVERFLOW) {
status = LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL;
}
ldns_pkt_set_edns_extended_rcode(packet, data[0]);
ldns_pkt_set_edns_version(packet, data[1]);
ldns_pkt_set_edns_z(packet, ldns_read_uint16(&data[2]));
- /* edns might not have rdfs */
- if (ldns_rr_rdf(rr, 0)) {
- ldns_rdf_deep_free(ldns_pkt_edns_data(packet));
- ldns_pkt_set_edns_data(packet, ldns_rdf_clone(ldns_rr_rdf(rr, 0)));
+ /* edns is already parsed here in ldns_wire2rr_additional() */
+
+ if (packet->_edns_options != NULL) {
+ edns = packet->_edns_options; // @TODO loop-ify
+
+
+ printf("HERE: edns code: %d\n", ldns_edns_get_code(edns));
+
+ // ldns_rdf_deep_free(ldns_pkt_edns_data(packet));
+ // ldns_pkt_set_edns_data(packet, ldns_edns_get_data(edns));
}
ldns_rr_free(rr);
have_edns += 1;