]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
add edns file and functionality in wire2host
authorTCY16 <tom@nlnetlabs.nl>
Wed, 30 Mar 2022 11:05:33 +0000 (13:05 +0200)
committerTCY16 <tom@nlnetlabs.nl>
Wed, 30 Mar 2022 11:05:33 +0000 (13:05 +0200)
.gitignore
Makefile.in
drill/drill.c
edns.c [new file with mode: 0644]
host2str.c
ldns/edns.h [new file with mode: 0644]
ldns/ldns.h
ldns/packet.h
ldns/rr.h
packet.c
wire2host.c

index 906e2876abd058b6a104e1bdeed892d338cb058e..4e0296ba9ca61665f42c72d81a1753dd93a86e66 100644 (file)
@@ -62,6 +62,8 @@
 /duration.o
 /error.lo
 /error.o
+/edns.lo
+/edns.o
 /examples/.libs/
 /examples/ldns-chaos
 /examples/ldns-chaos.lo
index 574098c69711c0bcae5576b5b5eb85ed3d5024b9..4cd4c90674ff8a25ac6fe44258c16ded5bc831c9 100644 (file)
@@ -89,12 +89,12 @@ DEPFLAG             = @DEPFLAG@
 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
 
@@ -799,6 +799,7 @@ zone.lo zone.o: $(srcdir)/zone.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.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
index 13afb84ff2c94efd88bdd57864479515561245ca..07695f60f1eab427dd45c22267e8895fc253e8e8 100644 (file)
@@ -699,6 +699,8 @@ main(int argc, char *argv[])
                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:
diff --git a/edns.c b/edns.c
new file mode 100644 (file)
index 0000000..2f6d809
--- /dev/null
+++ b/edns.c
@@ -0,0 +1,98 @@
+/*
+ * 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);
+    }
+}
index a207a9132b881700a995609e2d1a987264ff39b6..91fbc753697b6f3920fdcebdc24dffd34a3e6028 100644 (file)
@@ -2205,6 +2205,10 @@ ldns_pkt2buffer_str_fmt(ldns_buffer *output,
 
                        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");
diff --git a/ldns/edns.h b/ldns/edns.h
new file mode 100644 (file)
index 0000000..e710050
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * 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
index 60663ef95c7f3f8563106dab4ea0f5eb6c5ab74d..74713a211ae812b7e8ddcdc7a583ac48eb3c1698 100644 (file)
@@ -123,6 +123,7 @@ Or you can just use the menu above to browse through the API docs.
 #include <ldns/rbtree.h>
 #include <ldns/sha1.h>
 #include <ldns/sha2.h>
+#include <ldns/edns.h>
 
 #ifdef __cplusplus
 extern "C" {
index c0ed0c799f9098ead234f80826291f30b1b8bde7..73d04b099d2663591bb7a450bbbc2dddb6f0334d 100644 (file)
@@ -36,6 +36,7 @@
 #include <ldns/common.h>
 #include <ldns/rr.h>
 #include <sys/time.h>
+#include <ldns/edns.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -257,6 +258,10 @@ struct ldns_struct_pkt
        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 */
@@ -719,7 +724,7 @@ uint16_t ldns_pkt_edns_unassigned(const ldns_pkt *packet);
 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.
@@ -760,6 +765,18 @@ void ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z);
  */
 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
index 2b03a60e219bbe1c12ac989f6a759fa36af50608..44d54121f4d5a5c0ec9aa3f741964db149c9aa62 100644 (file)
--- a/ldns/rr.h
+++ b/ldns/rr.h
@@ -156,7 +156,7 @@ enum ldns_enum_rr_type
        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,
index a57e1901e008a388a437c9818f9b80a7ea8fa73e..0cee38f1f5c7f1d052de08800af26f66bea0c1d7 100644 (file)
--- a/packet.c
+++ b/packet.c
@@ -798,6 +798,8 @@ ldns_pkt_new(void)
        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;
index ee70fbdeb34e9e6395f00751da3a4891af6560a9..ab5fdd1b3702e1249bdf22dd1a3bab44fd676a69 100644 (file)
@@ -185,7 +185,7 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
        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;
@@ -312,6 +312,104 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
 }
 
 
+
+/* 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)?
@@ -411,6 +509,8 @@ ldns_wire2pkt(ldns_pkt **packet_p, const uint8_t *wire, size_t max)
        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];
 
@@ -418,6 +518,8 @@ ldns_wire2pkt(ldns_pkt **packet_p, const uint8_t *wire, size_t max)
                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);
 
@@ -456,7 +558,10 @@ ldns_wire2pkt(ldns_pkt **packet_p, const uint8_t *wire, size_t max)
                }
        }
        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;
                }
@@ -468,10 +573,16 @@ ldns_wire2pkt(ldns_pkt **packet_p, const uint8_t *wire, size_t max)
                        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;