]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add fr_dhcpv6_encode_dbuff()
authorJames Jones <jejones3141@gmail.com>
Tue, 20 Oct 2020 14:45:00 +0000 (09:45 -0500)
committerAlan DeKok <aland@freeradius.org>
Tue, 3 Nov 2020 13:09:02 +0000 (08:09 -0500)
src/protocols/dhcpv6/base.c
src/protocols/dhcpv6/dhcpv6.h

index 254e0d6206c5e85f43b5ae68d1c3f6390da89164..e17403be2a10af5149767967452bef38f5f438b4 100644 (file)
@@ -737,16 +737,18 @@ void *fr_dhcpv6_next_encodable(void **prev, void *to_eval, void *uctx)
  */
 ssize_t        fr_dhcpv6_encode(uint8_t *packet, size_t packet_len, uint8_t const *original, size_t length,
                         int msg_type, fr_pair_t *vps)
+{
+       return fr_dhcpv6_encode_dbuff(&FR_DBUFF_TMP(packet, packet_len), original, length, msg_type, vps);
+}
+
+ssize_t        fr_dhcpv6_encode_dbuff(fr_dbuff_t *dbuff, uint8_t const *original, size_t length, int msg_type, fr_pair_t *vps)
 {
        fr_pair_t *vp;
        fr_dict_attr_t const *root;
-       uint8_t *p, *end;
        ssize_t slen;
        fr_cursor_t cursor;
        fr_dhcpv6_encode_ctx_t packet_ctx;
 
-       if (packet_len < 4) return -1;
-
        root = fr_dict_root(dict_dhcpv6);
 
        if (!msg_type) {
@@ -759,67 +761,62 @@ ssize_t   fr_dhcpv6_encode(uint8_t *packet, size_t packet_len, uint8_t const *orig
                return -1;
        }
 
-       packet[0] = msg_type;
+       FR_DBUFF_BYTES_IN_RETURN(dbuff, (uint8_t) msg_type);
 
-       if (msg_type == FR_DHCPV6_RELAY_REPLY) {
-               if (packet_len < 2 + 32) return -1;
+       switch (msg_type) {
+       case FR_DHCPV6_RELAY_REPLY:
                if (!original) return -1;
 
-               memcpy(packet + 1, original + 1, 1 + 32);
-
-               p = packet + 2 + 32;
-               goto encode_options;
-       }
+               FR_DBUFF_MEMCPY_IN_RETURN(dbuff, original + 1, 1 + 32);
+               break;
 
-       if (msg_type == FR_DHCPV6_RELAY_FORWARD) {
-               if (packet_len < 2 + 32) return -1;
+       case FR_DHCPV6_RELAY_FORWARD:
+               FR_DBUFF_EXTEND_LOWAT_OR_RETURN(dbuff, 1 + 32);
 
                vp = fr_pair_find_by_da(vps, attr_hop_count);
-               if (vp) (void) fr_value_box_to_network(NULL, packet + 1, packet_len - 1, &vp->data);
+               if (vp) (void) fr_value_box_to_network_dbuff(NULL, dbuff, &vp->data);
 
                vp = fr_pair_find_by_da(vps, attr_relay_link_address);
-               if (vp) (void) fr_value_box_to_network(NULL, packet + 2, packet_len - 2, &vp->data);
+               if (vp) (void) fr_value_box_to_network_dbuff(NULL, dbuff, &vp->data);
 
                vp = fr_pair_find_by_da(vps, attr_relay_peer_address);
-               if (vp) (void) fr_value_box_to_network(NULL, packet + 2 + 16, packet_len - 2 - 16, &vp->data);
+               if (vp) (void) fr_value_box_to_network_dbuff(NULL, dbuff, &vp->data);
 
-               p = packet + 2 + 32;
-               goto encode_options;
-       }
+               break;
 
-       /*
-        *      Copy over original transaction ID if we have it.
-        */
-       if (original) {
-               memcpy(packet + 1, original + 1, 3);
-       } else {
+       default:
                /*
-                *      We can set an XID, or we can pick a random one.
+                *      Copy over original transaction ID if we have it.
                 */
-               vp = fr_pair_find_by_da(vps, attr_transaction_id);
-               if (vp && (vp->vp_length >= 3)) {
-                       memcpy(packet + 1, vp->vp_octets, 3);
+               if (original) {
+                       FR_DBUFF_MEMCPY_IN_RETURN(dbuff, original + 1, 3);
                } else {
-                       uint32_t id = fr_rand();
-
-                       packet[1] = (id >> 16) & 0xff;
-                       packet[2] = (id >> 8) & 0xff;
-                       packet[3] = id & 0xff;
+                       /*
+                        *      We can set an XID, or we can pick a random one.
+                        */
+                       vp = fr_pair_find_by_da(vps, attr_transaction_id);
+                       if (vp && (vp->vp_length >= 3)) {
+                               FR_DBUFF_MEMCPY_IN_RETURN(dbuff, vp->vp_octets, 3);
+                       } else {
+                               uint8_t id[sizeof(uint32_t)];
+
+                               fr_net_from_uint32(id, fr_rand());
+                               FR_DBUFF_MEMCPY_IN_RETURN(dbuff, &id[1], 3);
+                       }
                }
+               break;
        }
 
-       p = packet + 4;
-
-encode_options:
+       /*
+        * Encode options.
+        */
        packet_ctx.root = root;
        packet_ctx.original = original;
        packet_ctx.original_length = length;
 
-       end = packet + packet_len;
-
        fr_cursor_talloc_iter_init(&cursor, &vps, fr_dhcpv6_next_encodable, dict_dhcpv6, fr_pair_t);
-       while ((p < end) && (fr_cursor_current(&cursor) != NULL)) {
-               slen = fr_dhcpv6_encode_option(p, end - p, &cursor, &packet_ctx);
+       while ((fr_dbuff_extend(dbuff) > 0) && (fr_cursor_current(&cursor) != NULL)) {
+               slen = fr_dhcpv6_encode_option_dbuff(dbuff, &cursor, &packet_ctx);
                switch (slen) {
                case PAIR_ENCODE_SKIPPED:
                        continue;
@@ -832,12 +829,10 @@ encode_options:
 
                }
 
-               if (slen < 0) return slen - (p - packet);
-
-               p += slen;
+               if (slen < 0) return slen - fr_dbuff_used(dbuff);
        }
 
-       return p - packet;
+       return fr_dbuff_used(dbuff);
 }
 
 /**  Bootstrap a reply from the request
index 04e0c33f865495f980d0fbcde9e9baa477462cb5..d872bc53ef1190ecb673b85f8df1bdd0912e6e73 100644 (file)
@@ -141,6 +141,10 @@ bool               fr_dhcpv6_verify(uint8_t const *packet, size_t packet_len, fr_dhcpv6_decod
 ssize_t                fr_dhcpv6_encode(uint8_t *packet, size_t packet_len, uint8_t const *original, size_t length,
                                 int msg_type, fr_pair_t *vps);
 
+ssize_t                fr_dhcpv6_encode_dbuff(fr_dbuff_t *dbuff, uint8_t const *original, size_t length,
+                                int msg_type, fr_pair_t *vps);
+
+
 ssize_t                fr_dhcpv6_decode(TALLOC_CTX *ctx, uint8_t const *packet, size_t packet_len,
                                 fr_cursor_t *cursor);