]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- sldns updated for vfixed and buffer resize indication from getdns.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 16 Feb 2017 09:48:03 +0000 (09:48 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 16 Feb 2017 09:48:03 +0000 (09:48 +0000)
git-svn-id: file:///svn/unbound/trunk@4014 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
sldns/rrdef.h
sldns/sbuffer.c
sldns/sbuffer.h
sldns/wire2str.c

index b7a90e55726725c945c1ab9d6ea79e9a73553358..a555be3c9b8e12b210baa9cdfc5e8908eaca27e4 100644 (file)
@@ -1,3 +1,6 @@
+16 February 2017: Wouter
+       - sldns updated for vfixed and buffer resize indication from getdns.
+
 15 February 2017: Wouter
        - sldns has ED25519 and ED448 algorithm number and name for display.
 
index 44e9b84ce86a1f634f9248dce593020626c06e6d..618e62c67c3630d6cdcad73db7fd4ed47e19a08f 100644 (file)
@@ -423,6 +423,7 @@ enum sldns_enum_edns_option
        LDNS_EDNS_DHU = 6, /* RFC6975 */
        LDNS_EDNS_N3U = 7, /* RFC6975 */
        LDNS_EDNS_CLIENT_SUBNET = 8, /* draft-vandergaast-edns-client-subnet */
+       LDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/
        LDNS_EDNS_PADDING = 12 /* RFC7830 */
 };
 typedef enum sldns_enum_edns_option sldns_edns_option;
index a7fe53aa0278f99f1649097c21dd4d57c03e506a..a04b9b65563310134384988bbc44e970cde04a10 100644 (file)
@@ -33,6 +33,7 @@ sldns_buffer_new(size_t capacity)
        buffer->_position = 0;
        buffer->_limit = buffer->_capacity = capacity;
        buffer->_fixed = 0;
+       buffer->_vfixed = 0;
        buffer->_status_err = 0;
        
        sldns_buffer_invariant(buffer);
@@ -48,6 +49,7 @@ sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size)
        buffer->_position = 0; 
        buffer->_limit = buffer->_capacity = size;
        buffer->_fixed = 0;
+       buffer->_vfixed = 0;
        buffer->_data = malloc(size);
        if(!buffer->_data) {
                buffer->_status_err = 1;
@@ -66,6 +68,17 @@ sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size)
        buffer->_data = data;
        buffer->_capacity = buffer->_limit = size;
        buffer->_fixed = 1;
+       buffer->_vfixed = 0;
+}
+
+void
+sldns_buffer_init_vfixed_frm_data(sldns_buffer *buffer, void *data, size_t size)
+{
+       memset(buffer, 0, sizeof(*buffer));
+       buffer->_data = data;
+       buffer->_capacity = buffer->_limit = size;
+       buffer->_fixed = 1;
+       buffer->_vfixed = 1;
 }
 
 int
@@ -74,7 +87,7 @@ sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity)
        void *data;
        
        sldns_buffer_invariant(buffer);
-       assert(buffer->_position <= capacity);
+       assert(buffer->_position <= capacity && !buffer->_fixed);
 
        data = (uint8_t *) realloc(buffer->_data, capacity);
        if (!data) {
@@ -126,7 +139,7 @@ sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
                if (written == -1) {
                        buffer->_status_err = 1;
                        return -1;
-               } else if ((size_t) written >= remaining) {
+               } else if (!buffer->_vfixed && (size_t) written >= remaining) {
                        if (!sldns_buffer_reserve(buffer, (size_t) written + 1)) {
                                buffer->_status_err = 1;
                                return -1;
index 3ce874fc7f7605aef140a87716da10c1159b138d..c3b95e13dc8adeea8f5c4cdeb5777c54cd74c684 100644 (file)
@@ -87,6 +87,19 @@ sldns_write_uint32(void *dst, uint32_t data)
 }
 
 
+INLINE void
+sldns_write_uint48(void *dst, uint64_t data)
+{
+        uint8_t *p = (uint8_t *) dst;
+        p[0] = (uint8_t) ((data >> 40) & 0xff);
+        p[1] = (uint8_t) ((data >> 32) & 0xff);
+        p[2] = (uint8_t) ((data >> 24) & 0xff);
+        p[3] = (uint8_t) ((data >> 16) & 0xff);
+        p[4] = (uint8_t) ((data >> 8) & 0xff);
+        p[5] = (uint8_t) (data & 0xff);
+}
+
+
 /**
  * \file sbuffer.h
  *
@@ -117,6 +130,17 @@ struct sldns_buffer
        /** If the buffer is fixed it cannot be resized */
        unsigned _fixed : 1;
 
+       /** If the buffer is vfixed, no more than capacity bytes willl be
+        * written to _data, however the _position counter will be updated
+        * with the amount that would have been written in consecutive
+        * writes.  This allows for a modus operandi in which a sequence is
+        * written on a fixed capacity buffer (perhaps with _data on stack).
+        * When everything could be written, then the _data is immediately
+        * usable, if not, then a buffer could be allocated sized precisely
+        * to fit the data for a second attempt.
+        */
+       unsigned _vfixed : 1;
+
        /** The current state of the buffer. If writing to the buffer fails
         * for any reason, this value is changed. This way, you can perform
         * multiple writes in sequence and check for success afterwards. */
@@ -134,9 +158,9 @@ INLINE void
 sldns_buffer_invariant(sldns_buffer *buffer)
 {
        assert(buffer != NULL);
-       assert(buffer->_position <= buffer->_limit);
+       assert(buffer->_position <= buffer->_limit || buffer->_vfixed);
        assert(buffer->_limit <= buffer->_capacity);
-       assert(buffer->_data != NULL);
+       assert(buffer->_data != NULL || (buffer->_vfixed && buffer->_capacity == 0));
 }
 #endif
 
@@ -168,6 +192,19 @@ void sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size);
  */
 void sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size);
 
+/**
+ * Setup a buffer with the data pointed to. No data copied, no memory allocs.
+ * The buffer is "virtually" fixed.  Writes beyond size (the capacity) will
+ * only update position, but no data will be written beyond capacity.  This
+ * allows to determine how big the buffer should have been to contain all the
+ * written data, by looking at the position with sldns_buffer_position(),
+ * similarly to the return value of POSIX's snprintf.
+ * \param[in] buffer pointer to the buffer to put the data in
+ * \param[in] data the data to encapsulate in the buffer
+ * \param[in] size the size of the data
+ */
+void sldns_buffer_init_vfixed_frm_data(sldns_buffer *buffer, void *data, size_t size);
+
 /**
  * clears the buffer and make it ready for writing.  The buffer's limit
  * is set to the capacity and the position is set to 0.
@@ -231,7 +268,7 @@ sldns_buffer_position(sldns_buffer *buffer)
 INLINE void
 sldns_buffer_set_position(sldns_buffer *buffer, size_t mark)
 {
-       assert(mark <= buffer->_limit);
+       assert(mark <= buffer->_limit || buffer->_vfixed);
        buffer->_position = mark;
 }
 
@@ -245,7 +282,7 @@ sldns_buffer_set_position(sldns_buffer *buffer, size_t mark)
 INLINE void
 sldns_buffer_skip(sldns_buffer *buffer, ssize_t count)
 {
-       assert(buffer->_position + count <= buffer->_limit);
+       assert(buffer->_position + count <= buffer->_limit || buffer->_vfixed);
        buffer->_position += count;
 }
 
@@ -317,7 +354,7 @@ int sldns_buffer_reserve(sldns_buffer *buffer, size_t amount);
 INLINE uint8_t *
 sldns_buffer_at(const sldns_buffer *buffer, size_t at)
 {
-       assert(at <= buffer->_limit);
+       assert(at <= buffer->_limit || buffer->_vfixed);
        return buffer->_data + at;
 }
 
@@ -367,8 +404,8 @@ INLINE size_t
 sldns_buffer_remaining_at(sldns_buffer *buffer, size_t at)
 {
        sldns_buffer_invariant(buffer);
-       assert(at <= buffer->_limit);
-       return buffer->_limit - at;
+       assert(at <= buffer->_limit || buffer->_vfixed);
+       return at < buffer->_limit ? buffer->_limit - at : 0;
 }
 
 /**
@@ -420,7 +457,15 @@ sldns_buffer_available(sldns_buffer *buffer, size_t count)
 INLINE void
 sldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count)
 {
-       assert(sldns_buffer_available_at(buffer, at, count));
+       if (!buffer->_vfixed)
+               assert(sldns_buffer_available_at(buffer, at, count));
+       else if (sldns_buffer_remaining_at(buffer, at) == 0)
+               return;
+       else if (count > sldns_buffer_remaining_at(buffer, at)) {
+               memcpy(buffer->_data + at, data,
+                   sldns_buffer_remaining_at(buffer, at));
+               return;
+       }
        memcpy(buffer->_data + at, data, count);
 }
 
@@ -469,6 +514,7 @@ sldns_buffer_write_string(sldns_buffer *buffer, const char *str)
 INLINE void
 sldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data)
 {
+       if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
        assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
        buffer->_data[at] = data;
 }
@@ -494,6 +540,7 @@ sldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data)
 INLINE void
 sldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data)
 {
+       if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
        assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
        sldns_write_uint16(buffer->_data + at, data);
 }
@@ -519,10 +566,25 @@ sldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data)
 INLINE void
 sldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data)
 {
+       if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
        assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
        sldns_write_uint32(buffer->_data + at, data);
 }
 
+/**
+ * writes the given 6 byte integer at the given position in the buffer
+ * \param[in] buffer the buffer
+ * \param[in] at the position in the buffer
+ * \param[in] data the (lower) 48 bits to write
+ */
+INLINE void
+sldns_buffer_write_u48_at(sldns_buffer *buffer, size_t at, uint64_t data)
+{
+       if (buffer->_vfixed && at + 6 > buffer->_limit) return;
+       assert(sldns_buffer_available_at(buffer, at, 6));
+       sldns_write_uint48(buffer->_data + at, data);
+}
+
 /**
  * writes the given 4 byte integer at the current position in the buffer
  * \param[in] buffer the buffer
@@ -535,6 +597,18 @@ sldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data)
        buffer->_position += sizeof(data);
 }
 
+/**
+ * writes the given 6 byte integer at the current position in the buffer
+ * \param[in] buffer the buffer
+ * \param[in] data the 48 bits to write
+ */
+INLINE void
+sldns_buffer_write_u48(sldns_buffer *buffer, uint64_t data)
+{
+       sldns_buffer_write_u48_at(buffer, buffer->_position, data);
+       buffer->_position += 6;
+}
+
 /**
  * copies count bytes of data at the given position to the given data-array
  * \param[in] buffer the buffer
index acb3532512c18d664c7c7a4ed517bbf7bb028b0a..0ccf3492d910515951a6f3f7ce30f3d67ba9242a 100644 (file)
@@ -167,6 +167,7 @@ static sldns_lookup_table sldns_edns_options_data[] = {
        { 6, "DHU" },
        { 7, "N3U" },
        { 8, "edns-client-subnet" },
+       { 11, "edns-tcp-keepalive"},
        { 12, "Padding" },
        { 0, NULL}
 };
@@ -1840,6 +1841,25 @@ int sldns_wire2str_edns_subnet_print(char** s, size_t* sl, uint8_t* data,
        return w;
 }
 
+int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl, uint8_t* data,
+       size_t len)
+{
+       int w = 0;
+       uint16_t timeout;
+       if(!(len == 0 || len == 2)) {
+               w += sldns_str_print(s, sl, "malformed keepalive ");
+               w += print_hex_buf(s, sl, data, len);
+               return w;
+       }
+       if(len == 0 ) {
+               w += sldns_str_print(s, sl, "no timeout value (only valid for client option) ");
+       } else {
+               timeout = sldns_read_uint16(data);
+               w += sldns_str_print(s, sl, "timeout value in units of 100ms %u", (int)timeout);
+       }
+       return w;
+}
+
 int sldns_wire2str_edns_option_print(char** s, size_t* sl,
        uint16_t option_code, uint8_t* optdata, size_t optlen)
 {
@@ -1868,6 +1888,9 @@ int sldns_wire2str_edns_option_print(char** s, size_t* sl,
        case LDNS_EDNS_CLIENT_SUBNET:
                w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen);
                break;
+        case LDNS_EDNS_KEEPALIVE:
+               w += sldns_wire2str_edns_keepalive_print(s, sl, optdata, optlen);
+               break;
        case LDNS_EDNS_PADDING:
                w += print_hex_buf(s, sl, optdata, optlen);
                break;