]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Convert all encoders from vp_cursor_t to fr_cursor_t
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 15 Feb 2018 20:33:22 +0000 (20:33 +0000)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 15 Feb 2018 20:33:29 +0000 (20:33 +0000)
Add (untested) code for DHCPv6 encoder

21 files changed:
src/lib/util/dict.c
src/main/unit_test_attribute.c
src/modules/proto_dhcpv4/rlm_dhcpv4.c
src/modules/rlm_eap/lib/base/eap_chbind.c
src/modules/rlm_eap/lib/sim/decode.c
src/modules/rlm_eap/lib/sim/encode.c
src/modules/rlm_eap/lib/sim/sim_proto.h
src/modules/rlm_eap/types/rlm_eap_aka/rlm_eap_aka.c
src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c
src/protocols/dhcpv4/decode.c
src/protocols/dhcpv4/dhcpv4.h
src/protocols/dhcpv4/encode.c
src/protocols/dhcpv4/packet.c
src/protocols/dhcpv6/base.c [new file with mode: 0644]
src/protocols/dhcpv6/dhcpv6.h
src/protocols/dhcpv6/encode.c
src/protocols/radius/base.c
src/protocols/radius/decode.c
src/protocols/radius/encode.c
src/protocols/radius/packet.c
src/protocols/radius/radius.h

index 3b4f5a3e763680923f74d60ca934fd02ad756904..b07c7eb48d38aaa6f0185cdca8366efc5361f154 100644 (file)
@@ -3637,9 +3637,9 @@ void fr_dict_print(fr_dict_attr_t const *da, int depth)
 
 /** Find a common ancestor that two TLV type attributes share
  *
- * @param a first TLV attribute.
- * @param b second TLV attribute.
- * @param is_ancestor Enforce a->b relationship (a is parent or ancestor of b).
+ * @param a            first TLV attribute.
+ * @param b            second TLV attribute.
+ * @param is_ancestor  Enforce a->b relationship (a is parent or ancestor of b).
  * @return
  *     - Common ancestor if one exists.
  *     - NULL if no common ancestor exists.
index fe4227a5fdfac96f762a36a2f6db25c6f0e3acfc..205e9d6301265030a0075be86672e76e97a201b6 100644 (file)
@@ -840,7 +840,7 @@ static void process_file(CONF_SECTION *features, fr_dict_t *dict, const char *ro
                }
 
                if (strcmp(test_type, "decode-tacacs") == 0) {
-                       vp_cursor_t cursor;
+                       fr_cursor_t cursor;
                        RADIUS_PACKET *packet = talloc(NULL, RADIUS_PACKET);
 
                        if (strcmp(p + 14, "-") == 0) {
@@ -866,9 +866,9 @@ static void process_file(CONF_SECTION *features, fr_dict_t *dict, const char *ro
                                continue;
                        }
 
-                       fr_pair_cursor_init(&cursor, &packet->vps);
+                       fr_cursor_init(&cursor, &packet->vps);
                        p = output;
-                       for (vp = fr_pair_cursor_first(&cursor); vp; vp = fr_pair_cursor_next(&cursor)) {
+                       for (vp = fr_cursor_head(&cursor); vp; vp = fr_cursor_next(&cursor)) {
                                fr_pair_snprint(p, sizeof(output) - (p - output), vp);
                                p += strlen(p);
 
@@ -970,7 +970,7 @@ static void process_file(CONF_SECTION *features, fr_dict_t *dict, const char *ro
                }
 
                if (strcmp(test_type, "decode-tacacs") == 0) {
-                       vp_cursor_t cursor;
+                       fr_cursor_t cursor;
                        RADIUS_PACKET *packet = talloc(NULL, RADIUS_PACKET);
 
                        if (strcmp(p + 14, "-") == 0) {
@@ -996,9 +996,9 @@ static void process_file(CONF_SECTION *features, fr_dict_t *dict, const char *ro
                                continue;
                        }
 
-                       fr_pair_cursor_init(&cursor, &packet->vps);
+                       fr_cursor_init(&cursor, &packet->vps);
                        p = output;
-                       for (vp = fr_pair_cursor_first(&cursor); vp; vp = fr_pair_cursor_next(&cursor)) {
+                       for (vp = fr_cursor_head(&cursor); vp; vp = fr_cursor_next(&cursor)) {
                                fr_pair_snprint(p, sizeof(output) - (p - output), vp);
                                p += strlen(p);
 
@@ -1071,7 +1071,7 @@ static void process_file(CONF_SECTION *features, fr_dict_t *dict, const char *ro
                if (strncmp(test_type, "decode-pair", 11) == 0) {
                        fr_test_point_pair_decode_t     *tp = NULL;
                        ssize_t                         dec_len = 0;
-                       vp_cursor_t                     cursor;
+                       fr_cursor_t                     cursor;
                        void                            *decoder_ctx = NULL;
 
                        p += load_test_point_by_command((void **)&tp, test_type, 11, "tp_decode") + 1;
@@ -1090,7 +1090,7 @@ static void process_file(CONF_SECTION *features, fr_dict_t *dict, const char *ro
                                }
                        }
 
-                       fr_pair_cursor_init(&cursor, &head);
+                       fr_cursor_init(&cursor, &head);
                        while (len > 0) {
                                dec_len = tp->func(tp_ctx, &cursor, attr, len, decoder_ctx);
                                if (dec_len < 0) {
@@ -1111,9 +1111,9 @@ static void process_file(CONF_SECTION *features, fr_dict_t *dict, const char *ro
                         */
                        if (head) {
                                p = output;
-                               for (vp = fr_pair_cursor_first(&cursor);
+                               for (vp = fr_cursor_head(&cursor);
                                     vp;
-                                    vp = fr_pair_cursor_next(&cursor)) {
+                                    vp = fr_cursor_next(&cursor)) {
                                        fr_pair_snprint(p, sizeof(output) - (p - output), vp);
                                        p += strlen(p);
 
@@ -1147,7 +1147,7 @@ static void process_file(CONF_SECTION *features, fr_dict_t *dict, const char *ro
                if (strncmp(test_type, "encode-pair", 11) == 0) {
                        fr_test_point_pair_encode_t     *tp = NULL;
                        ssize_t                         enc_len = 0;
-                       vp_cursor_t                     cursor;
+                       fr_cursor_t                     cursor;
                        void                            *encoder_ctx = NULL;
 
                        p += load_test_point_by_command((void **)&tp, test_type, 11, "tp_encode") + 1;
@@ -1164,8 +1164,8 @@ static void process_file(CONF_SECTION *features, fr_dict_t *dict, const char *ro
                        }
 
                        attr = data;
-                       fr_pair_cursor_init(&cursor, &head);
-                       while ((vp = fr_pair_cursor_current(&cursor))) {
+                       fr_cursor_init(&cursor, &head);
+                       while ((vp = fr_cursor_current(&cursor))) {
                                enc_len = tp->func(attr, data + sizeof(data) - attr, &cursor, encoder_ctx);
                                if (enc_len < 0) {
                                        char *out_p = output, *out_end = out_p + sizeof(output);
index 8dec454628916c11a639b3bc8dbba07f206f3a6c..d79f0ea823777205f7f163db9bcd14e60383765f 100644 (file)
@@ -52,7 +52,7 @@ static ssize_t dhcp_options_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outl
                                 UNUSED void const *mod_inst, UNUSED void const *xlat_inst,
                                 REQUEST *request, char const *fmt)
 {
-       vp_cursor_t     cursor;
+       fr_cursor_t     cursor;
        fr_cursor_t     src_cursor;
        vp_tmpl_t       *src;
        VALUE_PAIR      *vp, *head = NULL;
@@ -83,7 +83,7 @@ static ssize_t dhcp_options_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outl
                goto error;
        }
 
-       fr_pair_cursor_init(&cursor, &head);
+       fr_cursor_init(&cursor, &head);
 
        for (vp = tmpl_cursor_init(NULL, &src_cursor, request, src);
             vp;
@@ -91,9 +91,9 @@ static ssize_t dhcp_options_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outl
                uint8_t const   *p = vp->vp_octets, *end = p + vp->vp_length;
                ssize_t         len;
                VALUE_PAIR      *vps = NULL;
-               vp_cursor_t     options_cursor;
+               fr_cursor_t     options_cursor;
 
-               fr_pair_cursor_init(&options_cursor, &vps);
+               fr_cursor_init(&options_cursor, &vps);
                /*
                 *      Loop over all the options data
                 */
@@ -106,12 +106,13 @@ static ssize_t dhcp_options_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outl
                        }
                        p += len;
                }
-               fr_pair_cursor_merge(&cursor, vps);
+               fr_cursor_head(&options_cursor);
+               fr_cursor_merge(&cursor, &options_cursor);
        }
 
-       for (vp = fr_pair_cursor_first(&cursor);
+       for (vp = fr_cursor_head(&cursor);
             vp;
-            vp = fr_pair_cursor_next(&cursor)) {
+            vp = fr_cursor_next(&cursor)) {
                rdebug_pair(L_DBG_LVL_2, request, vp, "dhcp_options: ");
                decoded++;
        }
@@ -132,7 +133,7 @@ static ssize_t dhcp_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
                         UNUSED void const *mod_inst, UNUSED void const *xlat_inst,
                         REQUEST *request, char const *fmt)
 {
-       vp_cursor_t cursor;
+       fr_cursor_t cursor;
        VALUE_PAIR *vp;
        uint8_t binbuf[255];
        ssize_t len;
@@ -140,7 +141,7 @@ static ssize_t dhcp_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
        while (isspace((int) *fmt)) fmt++;
 
        if ((radius_copy_vp(request, &vp, request, fmt) < 0) || !vp) return 0;
-       fr_pair_cursor_init(&cursor, &vp);
+       fr_cursor_init(&cursor, &vp);
 
        len = fr_dhcpv4_encode_option(binbuf, sizeof(binbuf), &cursor, NULL);
        talloc_free(vp);
index 11233e83499239d5e87b5f58faba015330426773..400bf8e9dea58a15622b9f6ec66c3bdea597b1fa 100644 (file)
@@ -32,12 +32,12 @@ static bool chbind_build_response(REQUEST *request, CHBIND_REQ *chbind)
        size_t                  total;
        uint8_t                 *ptr, *end;
        VALUE_PAIR              const *vp;
-       vp_cursor_t             cursor;
+       fr_cursor_t             cursor;
 
        total = 0;
-       for (vp = fr_pair_cursor_init(&cursor, &request->reply->vps);
+       for (vp = fr_cursor_init(&cursor, &request->reply->vps);
             vp != NULL;
-            vp = fr_pair_cursor_next(&cursor)) {
+            vp = fr_cursor_next(&cursor)) {
                /*
                 *      Skip things which shouldn't be in channel bindings.
                 */
@@ -83,14 +83,14 @@ static bool chbind_build_response(REQUEST *request, CHBIND_REQ *chbind)
        ptr += 4;
        end = ptr + total;
 
-       fr_pair_cursor_init(&cursor, &request->reply->vps);
-       while ((vp = fr_pair_cursor_current(&cursor)) && (ptr < end)) {
+       fr_cursor_init(&cursor, &request->reply->vps);
+       while ((vp = fr_cursor_current(&cursor)) && (ptr < end)) {
                /*
                 *      Skip things which shouldn't be in channel bindings.
                 */
                if (vp->da->flags.encrypt != FLAG_ENCRYPT_NONE) {
                next:
-                       fr_pair_cursor_next(&cursor);
+                       fr_cursor_next(&cursor);
                        continue;
                }
                if (!vp->da->vendor && (vp->da->attr == FR_MESSAGE_AUTHENTICATOR)) goto next;
@@ -187,11 +187,11 @@ FR_CODE chbind_process(REQUEST *request, CHBIND_REQ *chbind)
        /* Add the channel binding attributes to the fake packet */
        data_len = chbind_get_data(chbind->request, CHBIND_NSID_RADIUS, &attr_data);
        if (data_len) {
-               vp_cursor_t cursor;
+               fr_cursor_t cursor;
 
                rad_assert(data_len <= talloc_array_length((uint8_t const *) chbind->request));
 
-               fr_pair_cursor_init(&cursor, &fake->packet->vps);
+               fr_cursor_init(&cursor, &fake->packet->vps);
                while (data_len > 0) {
                        fr_radius_ctx_t decoder_ctx = {
                                .root = fr_dict_root(fr_dict_internal)
index 2b57c11500921aabcc3f4db9eb53e19a023487e8..40b7a6fa2101d2b08c8b80babd68983f391c425b 100644 (file)
@@ -56,10 +56,10 @@ RCSID("$Id$")
  * of 32 bits, and includes the Type/Length fields.
  */
 
-static ssize_t sim_decode_pair_internal(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent,
+static ssize_t sim_decode_pair_internal(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_attr_t const *parent,
                                           uint8_t const *data, size_t data_len, void *decoder_ctx);
 
-static ssize_t sim_decode_pair_value(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent,
+static ssize_t sim_decode_pair_value(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_attr_t const *parent,
                                     uint8_t const *data, size_t const attr_len, size_t const data_len,
                                     void *decoder_ctx);
 
@@ -291,7 +291,7 @@ static int sim_array_members(size_t *out, size_t len, fr_dict_attr_t const *da)
        return len / element_len;
 }
 
-static ssize_t sim_decode_array(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+static ssize_t sim_decode_array(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                                fr_dict_attr_t const *parent,
                                uint8_t const *data, size_t const attr_len, UNUSED size_t data_len,
                                void *decoder_ctx)
@@ -362,7 +362,7 @@ static ssize_t sim_decode_array(TALLOC_CTX *ctx, vp_cursor_t *cursor,
  *     - Length on success.
  *     - < 0 on malformed attribute.
  */
-static ssize_t sim_decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+static ssize_t sim_decode_tlv(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                              fr_dict_attr_t const *parent,
                              uint8_t const *data, size_t const attr_len, size_t data_len,
                              void *decoder_ctx)
@@ -372,7 +372,7 @@ static ssize_t sim_decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor,
        ssize_t                 decr_len;
        fr_dict_attr_t const    *child;
        VALUE_PAIR              *head = NULL;
-       vp_cursor_t             tlv_cursor;
+       fr_cursor_t             tlv_cursor;
        ssize_t                 rcode;
 
        if (data_len < 2) {
@@ -406,7 +406,7 @@ static ssize_t sim_decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor,
        /*
         *  Record where we were in the list when packet_ctx function was called
         */
-       fr_pair_cursor_init(&tlv_cursor, &head);
+       fr_cursor_init(&tlv_cursor, &head);
        while ((size_t)(end - p) >= sizeof(uint32_t)) {
                uint8_t sim_at = p[0];
                size_t  sim_at_len = ((size_t)p[1]) << 2;
@@ -498,7 +498,9 @@ static ssize_t sim_decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor,
                if (rcode < 0) goto error;
                p += sim_at_len;
        }
-       fr_pair_cursor_merge(cursor, head);     /* Wind to the end of the new pairs */
+       fr_cursor_head(&tlv_cursor);
+       fr_cursor_tail(cursor);
+       fr_cursor_merge(cursor, &tlv_cursor);   /* Wind to the end of the new pairs */
        talloc_free(decr);
 
        return attr_len;
@@ -517,7 +519,7 @@ static ssize_t sim_decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor,
  *     - Length on success.
  *     - -1 on failure.
  */
-static ssize_t sim_decode_pair_value(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent,
+static ssize_t sim_decode_pair_value(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_attr_t const *parent,
                                     uint8_t const *data, size_t const attr_len, size_t const data_len,
                                     void *decoder_ctx)
 {
@@ -816,7 +818,7 @@ static ssize_t sim_decode_pair_value(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_di
 
 done:
        vp->type = VT_DATA;
-       fr_pair_cursor_append(cursor, vp);
+       fr_cursor_append(cursor, vp);
 
        return attr_len;
 }
@@ -835,7 +837,7 @@ done:
  *     - The number of bytes parsed.
  *     - -1 on error.
  */
-static ssize_t sim_decode_pair_internal(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent,
+static ssize_t sim_decode_pair_internal(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_attr_t const *parent,
                                        uint8_t const *data, size_t data_len, void *decoder_ctx)
 {
        uint8_t                 sim_at;
@@ -912,7 +914,7 @@ static ssize_t sim_decode_pair_internal(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr
  *     - The number of bytes parsed.
  *     - -1 on error.
  */
-ssize_t fr_sim_decode_pair(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+ssize_t fr_sim_decode_pair(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                           uint8_t const *data, size_t data_len, void *decoder_ctx)
 {
        fr_sim_decode_ctx_t     *packet_ctx = decoder_ctx;
@@ -946,7 +948,7 @@ ssize_t fr_sim_decode_pair(TALLOC_CTX *ctx, vp_cursor_t *cursor,
  *     - 0 on success.
  *     - -1 on failure.
  */
-int fr_sim_decode(REQUEST *request, vp_cursor_t *decoded,
+int fr_sim_decode(REQUEST *request, fr_cursor_t *decoded,
                  uint8_t const *data, size_t data_len, fr_sim_decode_ctx_t *decoder_ctx)
 {
        ssize_t                 rcode;
@@ -960,7 +962,7 @@ int fr_sim_decode(REQUEST *request, vp_cursor_t *decoded,
         *      Move the cursor to the end, so we know if
         *      any additional attributes were added.
         */
-       fr_pair_cursor_end(decoded);
+       fr_cursor_tail(decoded);
 
        /*
         *      We need at least enough data for the subtype
@@ -988,7 +990,7 @@ int fr_sim_decode(REQUEST *request, vp_cursor_t *decoded,
                if (rcode <= 0) {
                        RPEDEBUG("Failed decoding AT");
                error:
-                       fr_pair_cursor_free(decoded);   /* Free any attributes we added */
+                       fr_cursor_free_list(decoded);   /* Free any attributes we added */
                        return -1;
                }
 
@@ -1009,7 +1011,7 @@ int fr_sim_decode(REQUEST *request, vp_cursor_t *decoded,
                        goto error;
                }
                vp->vp_uint32 = data[0];
-               fr_pair_cursor_append(decoded, vp);
+               fr_cursor_append(decoded, vp);
        }
 
        return 0;
index f260098fd1e3f9e88045ebad02cc4f8d9a6aa133..97b4a394ef0386a820e4a36fa6861486176a018b 100644 (file)
@@ -56,7 +56,7 @@ RCSID("$Id$")
 
 static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen,
                              fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                             vp_cursor_t *cursor, void *encoder_ctx);
+                             fr_cursor_t *cursor, void *encoder_ctx);
 
 /** Find the next attribute to encode
  *
@@ -64,17 +64,17 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen,
  * @param encoder_ctx the context for the encoder
  * @return encodable VALUE_PAIR, or NULL if none available.
  */
-static inline VALUE_PAIR *next_encodable(vp_cursor_t *cursor, void *encoder_ctx)
+static inline VALUE_PAIR *next_encodable(fr_cursor_t *cursor, void *encoder_ctx)
 {
        VALUE_PAIR              *vp;
        fr_sim_encode_ctx_t     *packet_ctx = encoder_ctx;
 
-       for (;;) {
-               vp = fr_pair_cursor_next_by_ancestor(cursor, packet_ctx->root, TAG_ANY);
-               if (!vp || !vp->da->flags.internal) break;
+       while ((vp = fr_cursor_next(cursor))) {
+               if (vp->da->flags.internal) continue;
+               if (fr_dict_parent_common(packet_ctx->root, vp->da, true)) break;
        }
 
-       return fr_pair_cursor_current(cursor);
+       return fr_cursor_current(cursor);
 }
 
 /** Determine if the current attribute is encodable, or find the first one that is
@@ -83,16 +83,13 @@ static inline VALUE_PAIR *next_encodable(vp_cursor_t *cursor, void *encoder_ctx)
  * @param encoder_ctx the context for the encoder
  * @return encodable VALUE_PAIR, or NULL if none available.
  */
-static inline VALUE_PAIR *first_encodable(vp_cursor_t *cursor, void *encoder_ctx)
+static inline VALUE_PAIR *first_encodable(fr_cursor_t *cursor, void *encoder_ctx)
 {
        VALUE_PAIR              *vp;
        fr_sim_encode_ctx_t     *packet_ctx = encoder_ctx;
 
-       vp = fr_pair_cursor_current(cursor);
-       if (vp && !vp->da->flags.internal && fr_dict_parent_common(packet_ctx->root, vp->da, true)) {
-               cursor->found = vp;
-               return vp;
-       }
+       vp = fr_cursor_current(cursor);
+       if (vp && !vp->da->flags.internal && fr_dict_parent_common(packet_ctx->root, vp->da, true)) return vp;
 
        return next_encodable(cursor, encoder_ctx);
 }
@@ -297,10 +294,10 @@ static ssize_t encode_encrypted_value(uint8_t *out, size_t outlen,
  */
 static ssize_t encode_value(uint8_t *out, size_t outlen,
                            fr_dict_attr_t const **tlv_stack, int depth,
-                           vp_cursor_t *cursor, void *encoder_ctx)
+                           fr_cursor_t *cursor, void *encoder_ctx)
 {
        ssize_t                 len;
-       VALUE_PAIR const        *vp = fr_pair_cursor_current(cursor);
+       VALUE_PAIR const        *vp = fr_cursor_current(cursor);
        fr_dict_attr_t const    *da = tlv_stack[depth];
        fr_sim_encode_ctx_t     *packet_ctx = encoder_ctx;
 
@@ -554,7 +551,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen,
                if (2 > outlen) goto oos;
                out[0] = 0;
                out[1] = 0;
-               len = 2;
+               len = 2;        /* Length of the reserved area */
                break;
 
        /*
@@ -613,7 +610,7 @@ done:
  */
 static ssize_t encode_array(uint8_t *out, size_t outlen,
                            fr_dict_attr_t const **tlv_stack, int depth,
-                           vp_cursor_t *cursor, void *encoder_ctx)
+                           fr_cursor_t *cursor, void *encoder_ctx)
 {
        uint8_t                 *p = out, *end = p + outlen;
        uint8_t                 *value;
@@ -650,7 +647,7 @@ static ssize_t encode_array(uint8_t *out, size_t outlen,
 
                p += slen;
 
-               vp = fr_pair_cursor_current(cursor);
+               vp = fr_cursor_current(cursor);
                if (!vp || (vp->da != da)) break;               /* Stop if we have an attribute of a different type */
        }
 
@@ -693,7 +690,7 @@ static ssize_t encode_array(uint8_t *out, size_t outlen,
  * Otherwise, attribute may be something else.
  */
 static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                             vp_cursor_t *cursor, void *encoder_ctx)
+                             fr_cursor_t *cursor, void *encoder_ctx)
 {
        size_t                  pad_len;
        uint8_t                 *p = out, *end = p + outlen;
@@ -764,11 +761,11 @@ static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const
 
 static inline ssize_t encode_tlv(uint8_t *out, size_t outlen,
                                 fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                                vp_cursor_t *cursor, void *encoder_ctx)
+                                fr_cursor_t *cursor, void *encoder_ctx)
 {
        ssize_t                 slen;
        uint8_t                 *p = out, *end = p + outlen, *value;
-       VALUE_PAIR const        *vp = fr_pair_cursor_current(cursor);
+       VALUE_PAIR const        *vp = fr_cursor_current(cursor);
        fr_dict_attr_t const    *da = tlv_stack[depth];
 
        if (outlen < 2) {
@@ -806,7 +803,7 @@ static inline ssize_t encode_tlv(uint8_t *out, size_t outlen,
                /*
                 *      If nothing updated the attribute, stop
                 */
-               if (!fr_pair_cursor_current(cursor) || (vp == fr_pair_cursor_current(cursor))) break;
+               if (!fr_cursor_current(cursor) || (vp == fr_cursor_current(cursor))) break;
 
                /*
                 *      We can encode multiple sub TLVs, if after
@@ -814,7 +811,7 @@ static inline ssize_t encode_tlv(uint8_t *out, size_t outlen,
                 *      at this depth is the same.
                 */
                if (da != tlv_stack[depth]) break;
-               vp = fr_pair_cursor_current(cursor);
+               vp = fr_cursor_current(cursor);
        }
 
        /*
@@ -835,14 +832,14 @@ static inline ssize_t encode_tlv(uint8_t *out, size_t outlen,
 
 static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen,
                              fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                             vp_cursor_t *cursor, void *encoder_ctx)
+                             fr_cursor_t *cursor, void *encoder_ctx)
 {
        unsigned int            total_len;
        ssize_t                 len;
        uint8_t                 *p = out;
        fr_dict_attr_t const    *da;
 
-       VP_VERIFY(fr_pair_cursor_current(cursor));
+       VP_VERIFY(fr_cursor_current(cursor));
        FR_PROTO_STACK_PRINT(tlv_stack, depth);
 
        if (tlv_stack[depth]->type != FR_TYPE_TLV) {
@@ -891,7 +888,7 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen,
        return p - out; /* AT_IV + AT_*(TLV) - Can't use total_len, doesn't include IV */
 }
 
-ssize_t fr_sim_encode_pair(uint8_t *out, size_t outlen, vp_cursor_t *cursor, void *encoder_ctx)
+ssize_t fr_sim_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor, void *encoder_ctx)
 {
        VALUE_PAIR const        *vp;
        int                     ret;
@@ -962,7 +959,7 @@ ssize_t fr_sim_encode_pair(uint8_t *out, size_t outlen, vp_cursor_t *cursor, voi
        /*
         *      We couldn't do it, so we didn't do anything.
         */
-       if (fr_pair_cursor_current(cursor) == vp) {
+       if (fr_cursor_current(cursor) == vp) {
                fr_strerror_printf("%s: Nested attribute structure too large to encode", __FUNCTION__);
                return -1;
        }
@@ -981,7 +978,7 @@ ssize_t fr_sim_encode(REQUEST *request, VALUE_PAIR *to_encode, void *encode_ctx)
        bool                    do_hmac = false;
 
        unsigned char           subtype;
-       vp_cursor_t             cursor;
+       fr_cursor_t             cursor;
        fr_sim_encode_ctx_t     *packet_ctx = encode_ctx;
        eap_packet_t            *eap_packet = packet_ctx->eap_packet;
 
@@ -1001,7 +998,7 @@ ssize_t fr_sim_encode(REQUEST *request, VALUE_PAIR *to_encode, void *encode_ctx)
         *      Group attributes with similar lineages together
         */
        fr_pair_list_sort(&to_encode, fr_pair_cmp_by_parent_num_tag);
-       (void)fr_pair_cursor_init(&cursor, &to_encode);
+       (void)fr_cursor_init(&cursor, &to_encode);
 
        /*
         *      Fast path...
@@ -1018,7 +1015,7 @@ ssize_t fr_sim_encode(REQUEST *request, VALUE_PAIR *to_encode, void *encode_ctx)
 
                return 0;
        }
-       fr_pair_cursor_first(&cursor);  /* Reset */
+       fr_cursor_head(&cursor);        /* Reset */
 
        MEM(p = buff = talloc_zero_array(eap_packet, uint8_t, 1024));   /* We'll shrink this later */
        end = p + talloc_array_length(p);
@@ -1051,8 +1048,8 @@ ssize_t fr_sim_encode(REQUEST *request, VALUE_PAIR *to_encode, void *encode_ctx)
        /*
         *      Encode all the things...
         */
-       (void)fr_pair_cursor_first(&cursor);
-       while ((vp = fr_pair_cursor_current(&cursor))) {
+       (void)fr_cursor_head(&cursor);
+       while ((vp = fr_cursor_current(&cursor))) {
                slen = fr_sim_encode_pair(p, end - p, &cursor, packet_ctx);
                if (slen < 0) {
                error:
index 61aa683dbbd8bd249ad2e8a448cefb7dfedcfc64..fb7f3c8abb56b565166be9cd91655ba7dbdb1f28 100644 (file)
@@ -230,16 +230,16 @@ extern fr_dict_attr_t const *dict_aka_root;
 /*
  *     decode.c
  */
-ssize_t                fr_sim_decode_pair(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+ssize_t                fr_sim_decode_pair(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                                   uint8_t const *data, size_t data_len, void *decoder_ctx);
 
-int            fr_sim_decode(REQUEST *request, vp_cursor_t *decoded,
+int            fr_sim_decode(REQUEST *request, fr_cursor_t *decoded,
                              uint8_t const *data, size_t data_len, fr_sim_decode_ctx_t *ctx);
 
 /*
  *     encode.c
  */
-ssize_t                fr_sim_encode_pair(uint8_t *out, size_t outlen, vp_cursor_t *cursor, void *encoder_ctx);
+ssize_t                fr_sim_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor, void *encoder_ctx);
 
 ssize_t                fr_sim_encode(REQUEST *request, VALUE_PAIR *to_encode, void *encode_ctx);
 
index 477d3cc13122812fdf7bee0db3d48eba6f7af84a..ee59cd0fe54e3b92c0b995cfaab43ef775bafc4b 100644 (file)
@@ -60,8 +60,8 @@ static CONF_PARSER submodule_config[] = {
 static int eap_aka_compose(eap_session_t *eap_session)
 {
        eap_aka_session_t       *eap_aka_session = talloc_get_type_abort(eap_session->opaque, eap_aka_session_t);
-       vp_cursor_t             cursor;
-       vp_cursor_t             to_encode;
+       fr_cursor_t             cursor;
+       fr_cursor_t             to_encode;
        VALUE_PAIR              *head = NULL, *vp;
        REQUEST                 *request = eap_session->request;
        ssize_t                 ret;
@@ -80,11 +80,15 @@ static int eap_aka_compose(eap_session_t *eap_session)
                                };
        fr_dict_attr_t const    *encr = fr_dict_attr_child_by_num(dict_sim_root, FR_EAP_AKA_ENCR_DATA);
 
-       fr_pair_cursor_init(&cursor, &eap_session->request->reply->vps);
-       fr_pair_cursor_init(&to_encode, &head);
+       fr_cursor_init(&cursor, &eap_session->request->reply->vps);
+       fr_cursor_init(&to_encode, &head);
 
-       while ((fr_pair_cursor_next_by_ancestor(&cursor, dict_aka_root, TAG_ANY))) {
-               vp = fr_pair_cursor_remove(&cursor);
+       while ((vp = fr_cursor_current(&cursor))) {
+               if (!fr_dict_parent_common(dict_aka_root, vp->da, true)) {
+                       fr_cursor_next(&cursor);
+                       continue;
+               }
+               vp = fr_cursor_remove(&cursor);
 
                /*
                 *      Silently discard encrypted attributes until
@@ -99,7 +103,7 @@ static int eap_aka_compose(eap_session_t *eap_session)
                        continue;
                }
 
-               fr_pair_cursor_append(&to_encode, vp);
+               fr_cursor_append(&to_encode, vp);
        }
 
        RDEBUG2("Encoding EAP-AKA attributes");
@@ -110,8 +114,8 @@ static int eap_aka_compose(eap_session_t *eap_session)
        eap_session->this_round->set_request_id = true;
 
        ret = fr_sim_encode(eap_session->request, head, &encoder_ctx);
-       fr_pair_cursor_first(&to_encode);
-       fr_pair_cursor_free(&to_encode);
+       fr_cursor_head(&to_encode);
+       fr_cursor_free_list(&to_encode);
 
        if (ret < 0) {
                RPEDEBUG("Failed encoding EAP-AKA data");
@@ -812,7 +816,7 @@ static rlm_rcode_t mod_process(UNUSED void *arg, eap_session_t *eap_session)
                                        .root = dict_aka_root
                                };
        VALUE_PAIR              *vp, *vps, *subtype_vp;
-       vp_cursor_t             cursor;
+       fr_cursor_t             cursor;
 
        eap_aka_subtype_t       subtype;
 
@@ -831,8 +835,8 @@ static rlm_rcode_t mod_process(UNUSED void *arg, eap_session_t *eap_session)
        /* vps is the data from the client */
        vps = request->packet->vps;
 
-       fr_pair_cursor_init(&cursor, &request->packet->vps);
-       fr_pair_cursor_last(&cursor);
+       fr_cursor_init(&cursor, &request->packet->vps);
+       fr_cursor_tail(&cursor);
 
        ret = fr_sim_decode(eap_session->request,
                            &cursor,
@@ -850,7 +854,7 @@ static rlm_rcode_t mod_process(UNUSED void *arg, eap_session_t *eap_session)
                return RLM_MODULE_HANDLED;      /* We need to process more packets */
        }
 
-       vp = fr_pair_cursor_current(&cursor);
+       vp = fr_cursor_current(&cursor);
        if (vp && RDEBUG_ENABLED2) {
                RDEBUG2("EAP-AKA decoded attributes");
                rdebug_pair_list(L_DBG_LVL_2, request, vp, NULL);
index 2c45aaef06bf5c3c6131cf4edbde48150ae6908e..e67cdc890c805ca8b2c3c1791dab7cf19171390a 100644 (file)
@@ -62,8 +62,8 @@ static CONF_PARSER submodule_config[] = {
 static int eap_sim_compose(eap_session_t *eap_session, uint8_t const *hmac_extra, size_t hmac_extra_len)
 {
        eap_sim_session_t       *eap_sim_session = talloc_get_type_abort(eap_session->opaque, eap_sim_session_t);
-       vp_cursor_t             cursor;
-       vp_cursor_t             to_encode;
+       fr_cursor_t             cursor;
+       fr_cursor_t             to_encode;
        VALUE_PAIR              *head = NULL, *vp;
        REQUEST                 *request = eap_session->request;
        fr_sim_encode_ctx_t     encoder_ctx = {
@@ -86,11 +86,15 @@ static int eap_sim_compose(eap_session_t *eap_session, uint8_t const *hmac_extra
        /* we will set the ID on requests, since we have to HMAC it */
        eap_session->this_round->set_request_id = true;
 
-       fr_pair_cursor_init(&cursor, &eap_session->request->reply->vps);
-       fr_pair_cursor_init(&to_encode, &head);
+       fr_cursor_init(&cursor, &eap_session->request->reply->vps);
+       fr_cursor_init(&to_encode, &head);
 
-       while ((fr_pair_cursor_next_by_ancestor(&cursor, dict_sim_root, TAG_ANY))) {
-               vp = fr_pair_cursor_remove(&cursor);
+       while ((vp = fr_cursor_current(&cursor))) {
+               if (!fr_dict_parent_common(dict_sim_root, vp->da, true)) {
+                       fr_cursor_next(&cursor);
+                       continue;
+               }
+               vp = fr_cursor_remove(&cursor);
 
                /*
                 *      Silently discard encrypted attributes until
@@ -105,7 +109,7 @@ static int eap_sim_compose(eap_session_t *eap_session, uint8_t const *hmac_extra
                        continue;
                }
 
-               fr_pair_cursor_append(&to_encode, vp);
+               fr_cursor_append(&to_encode, vp);
        }
 
        RDEBUG2("Encoding EAP-SIM attributes");
@@ -116,8 +120,8 @@ static int eap_sim_compose(eap_session_t *eap_session, uint8_t const *hmac_extra
        eap_session->this_round->set_request_id = true;
 
        ret = fr_sim_encode(eap_session->request, head, &encoder_ctx);
-       fr_pair_cursor_first(&to_encode);
-       fr_pair_cursor_free(&to_encode);
+       fr_cursor_head(&to_encode);
+       fr_cursor_free_list(&to_encode);
 
        if (ret < 0) {
                RPEDEBUG("Failed encoding EAP-SIM data");
@@ -808,7 +812,7 @@ static rlm_rcode_t mod_process(UNUSED void *arg, eap_session_t *eap_session)
                                        .root = dict_sim_root
                                };
        VALUE_PAIR              *subtype_vp, *from_peer, *vp;
-       vp_cursor_t             cursor;
+       fr_cursor_t             cursor;
 
        eap_sim_subtype_t       subtype;
 
@@ -821,8 +825,8 @@ static rlm_rcode_t mod_process(UNUSED void *arg, eap_session_t *eap_session)
         */
        from_peer = eap_session->request->packet->vps;
 
-       fr_pair_cursor_init(&cursor, &request->packet->vps);
-       fr_pair_cursor_last(&cursor);
+       fr_cursor_init(&cursor, &request->packet->vps);
+       fr_cursor_tail(&cursor);
 
        ret = fr_sim_decode(eap_session->request,
                            &cursor,
@@ -840,7 +844,7 @@ static rlm_rcode_t mod_process(UNUSED void *arg, eap_session_t *eap_session)
                return RLM_MODULE_HANDLED;      /* We need to process more packets */
        }
 
-       vp = fr_pair_cursor_current(&cursor);
+       vp = fr_cursor_current(&cursor);
        if (vp && RDEBUG_ENABLED2) {
                RDEBUG2("Decoded EAP-SIM attributes");
                rdebug_pair_list(L_DBG_LVL_2, request, vp, NULL);
index baa897aadb88d5cc13aaff6978108984b12e95b2..ae331178a36b0a23a89f756cb8fa5ec24c8d7671 100644 (file)
 #include <freeradius-devel/dhcpv4/dhcpv4.h>
 #include <freeradius-devel/io/test_point.h>
 
-static ssize_t decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent,
+static ssize_t decode_tlv(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_attr_t const *parent,
                          uint8_t const *data, size_t data_len);
 
-static ssize_t decode_value(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+static ssize_t decode_value(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                            fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len);
 
 /** Returns the number of array members for arrays with fixed element sizes
@@ -84,7 +84,7 @@ static int fr_dhcpv4_array_members(size_t *out, size_t len, fr_dict_attr_t const
 /*
  *     Decode ONE value into a VP
  */
-static ssize_t decode_value_internal(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *da,
+static ssize_t decode_value_internal(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_attr_t const *da,
                                     uint8_t const *data, size_t data_len)
 {
        VALUE_PAIR *vp;
@@ -131,7 +131,7 @@ static ssize_t decode_value_internal(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_di
 
                        /* Need another VP for the next round */
                        if (p < end) {
-                               fr_pair_cursor_append(cursor, vp);
+                               fr_cursor_append(cursor, vp);
 
                                vp = fr_pair_afrom_da(ctx, da);
                                if (!vp) return -1;
@@ -180,7 +180,7 @@ static ssize_t decode_value_internal(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_di
 
 finish:
        FR_PROTO_TRACE("decoding value complete, adding new pair and returning %zu byte(s)", p - data);
-       fr_pair_cursor_append(cursor, vp);
+       fr_cursor_append(cursor, vp);
 
        return p - data;
 }
@@ -220,7 +220,7 @@ finish:
  * @param[in] data to parse.
  * @param[in] data_len of data parsed.
  */
-static ssize_t decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent,
+static ssize_t decode_tlv(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_attr_t const *parent,
                          uint8_t const *data, size_t data_len)
 {
        uint8_t const           *p = data;
@@ -300,7 +300,7 @@ static ssize_t decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t c
        return p - data;
 }
 
-static ssize_t decode_value(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+static ssize_t decode_value(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                            fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len)
 {
        unsigned int    values, i;              /* How many values we need to decode */
@@ -355,7 +355,7 @@ static ssize_t decode_value(TALLOC_CTX *ctx, vp_cursor_t *cursor,
  * @param[in] data_len of data to parse.
  * @param[in] decoder_ctx Unused.
  */
-ssize_t fr_dhcpv4_decode_option(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+ssize_t fr_dhcpv4_decode_option(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                                uint8_t const *data, size_t data_len, void *decoder_ctx)
 {
        ssize_t                 ret;
index 8820372d56d3a227bc5d9c1252a347188f4bbd63..364344dd4fb2dc045f7ac077e5790411688eab69 100644 (file)
@@ -158,14 +158,14 @@ int               fr_dhcpv4_init(void);
 /*
  *     decode.c
  */
-ssize_t                fr_dhcpv4_decode_option(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+ssize_t                fr_dhcpv4_decode_option(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                                        uint8_t const *data, size_t len, void *decoder_ctx);
 
 /*
  *     encode.c
  */
 ssize_t                fr_dhcpv4_encode_option(uint8_t *out, size_t outlen,
-                                       vp_cursor_t *cursor, void *encoder_ctx);
+                                       fr_cursor_t *cursor, void *encoder_ctx);
 
 /*
  *     packet.c
index 5985bb77f347394b5e1d2a624cb919e1b3b3f563..570eb98e8947ec081e3e821628001ba3221ea99e 100644 (file)
  */
 static ssize_t encode_value(uint8_t *out, size_t outlen,
                            fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                           vp_cursor_t *cursor)
+                           fr_cursor_t *cursor)
 {
        uint32_t lvalue;
 
-       VALUE_PAIR *vp = fr_pair_cursor_current(cursor);
+       VALUE_PAIR *vp = fr_cursor_current(cursor);
        uint8_t *p = out;
 
        FR_PROTO_STACK_PRINT(tlv_stack, depth);
@@ -106,10 +106,10 @@ static ssize_t encode_value(uint8_t *out, size_t outlen,
 
        default:
                fr_strerror_printf("Unsupported option type %d", vp->vp_type);
-               (void)fr_pair_cursor_next(cursor);
+               (void)fr_cursor_next(cursor);
                return -2;
        }
-       vp = fr_pair_cursor_next(cursor);       /* We encoded a leaf, advance the cursor */
+       vp = fr_cursor_next(cursor);    /* We encoded a leaf, advance the cursor */
        fr_proto_tlv_stack_build(tlv_stack, vp ? vp->da : NULL);
 
        FR_PROTO_STACK_PRINT(tlv_stack, depth);
@@ -133,12 +133,12 @@ static ssize_t encode_value(uint8_t *out, size_t outlen,
  *     - < 0 on error.
  */
 static ssize_t encode_rfc_hdr(uint8_t *out, ssize_t outlen,
-                             fr_dict_attr_t const **tlv_stack, unsigned int depth, vp_cursor_t *cursor)
+                             fr_dict_attr_t const **tlv_stack, unsigned int depth, fr_cursor_t *cursor)
 {
        ssize_t                 len;
        uint8_t                 *p = out;
        fr_dict_attr_t const    *da = tlv_stack[depth];
-       VALUE_PAIR              *vp = fr_pair_cursor_current(cursor);
+       VALUE_PAIR              *vp = fr_cursor_current(cursor);
 
        if (outlen < 3) return 0;       /* No space */
 
@@ -184,7 +184,7 @@ static ssize_t encode_rfc_hdr(uint8_t *out, ssize_t outlen,
 
                FR_PROTO_TRACE("%zu byte(s) available in option", outlen - out[1]);
 
-               next = fr_pair_cursor_current(cursor);
+               next = fr_cursor_current(cursor);
                if (!next || (vp->da != next->da)) break;
                vp = next;
        } while (vp->da->flags.array);
@@ -205,11 +205,11 @@ static ssize_t encode_rfc_hdr(uint8_t *out, ssize_t outlen,
  *     - < 0 on error.
  */
 static ssize_t encode_tlv_hdr(uint8_t *out, ssize_t outlen,
-                             fr_dict_attr_t const **tlv_stack, unsigned int depth, vp_cursor_t *cursor)
+                             fr_dict_attr_t const **tlv_stack, unsigned int depth, fr_cursor_t *cursor)
 {
        ssize_t                 len;
        uint8_t                 *p = out;
-       VALUE_PAIR const        *vp = fr_pair_cursor_current(cursor);
+       VALUE_PAIR const        *vp = fr_cursor_current(cursor);
        fr_dict_attr_t const    *da = tlv_stack[depth];
 
        if (outlen < 5) return 0;       /* No space */
@@ -254,7 +254,7 @@ static ssize_t encode_tlv_hdr(uint8_t *out, ssize_t outlen,
                /*
                 *      If nothing updated the attribute, stop
                 */
-               if (!fr_pair_cursor_current(cursor) || (vp == fr_pair_cursor_current(cursor))) break;
+               if (!fr_cursor_current(cursor) || (vp == fr_cursor_current(cursor))) break;
 
                /*
                 *      We can encode multiple sub TLVs, if after
@@ -262,7 +262,7 @@ static ssize_t encode_tlv_hdr(uint8_t *out, ssize_t outlen,
                 *      at this depth is the same.
                 */
                if (da != tlv_stack[depth]) break;
-               vp = fr_pair_cursor_current(cursor);
+               vp = fr_cursor_current(cursor);
        }
 
        return p - out;
@@ -279,14 +279,14 @@ static ssize_t encode_tlv_hdr(uint8_t *out, ssize_t outlen,
  *     - < 0 error.
  *     - 0 not valid option for DHCP (skipping).
  */
-ssize_t fr_dhcpv4_encode_option(uint8_t *out, size_t outlen, vp_cursor_t *cursor, UNUSED void *encoder_ctx)
+ssize_t fr_dhcpv4_encode_option(uint8_t *out, size_t outlen, fr_cursor_t *cursor, UNUSED void *encoder_ctx)
 {
        VALUE_PAIR              *vp;
        unsigned int            depth = 0;
        fr_dict_attr_t const    *tlv_stack[FR_DICT_MAX_TLV_STACK + 1];
        ssize_t                 len;
 
-       vp = fr_pair_cursor_current(cursor);
+       vp = fr_cursor_current(cursor);
        if (!vp) return -1;
 
        if (vp->da->vendor != DHCP_MAGIC_VENDOR) goto next; /* not a DHCP option */
@@ -294,7 +294,7 @@ ssize_t fr_dhcpv4_encode_option(uint8_t *out, size_t outlen, vp_cursor_t *cursor
        if ((vp->da->attr > 255) && (DHCP_BASE_ATTR(vp->da->attr) != FR_DHCPV4_OPTION_82)) {
        next:
                fr_strerror_printf("Attribute \"%s\" is not a DHCP option", vp->da->name);
-               fr_pair_cursor_next(cursor);
+               fr_cursor_next(cursor);
                return 0;
        }
 
index e347ce32382bb4ef7d880d8b399c20be29568f6e..8c3b3419f04e82ceb35c5f593eaa7e5c380a9af8 100644 (file)
@@ -104,11 +104,11 @@ int fr_dhcpv4_packet_decode(RADIUS_PACKET *packet)
        size_t i;
        uint8_t *p;
        uint32_t giaddr;
-       vp_cursor_t cursor;
+       fr_cursor_t cursor;
        VALUE_PAIR *head = NULL, *vp;
        VALUE_PAIR *maxms, *mtu;
 
-       fr_pair_cursor_init(&cursor, &head);
+       fr_cursor_init(&cursor, &head);
        p = packet->data;
 
        if (packet->data[1] > 1) {
@@ -196,7 +196,7 @@ int fr_dhcpv4_packet_decode(RADIUS_PACKET *packet)
 
                if (!vp) continue;
 
-               fr_pair_cursor_append(&cursor, vp);
+               fr_cursor_append(&cursor, vp);
        }
 
        /*
@@ -208,11 +208,11 @@ int fr_dhcpv4_packet_decode(RADIUS_PACKET *packet)
         *      it'll need to find the new tail...
         */
        {
-               uint8_t const   *end;
-               ssize_t         len;
+               uint8_t const           *end;
+               ssize_t                 len;
                fr_dhcp_decoder_ctx_t   packet_ctx = {
-                                       .root = fr_dict_root(fr_dict_internal)
-                               };
+                                               .root = fr_dict_root(fr_dict_internal)
+                                       };
 
                p = packet->data + 240;
                end = p + (packet->data_len - 240);
@@ -297,7 +297,7 @@ int fr_dhcpv4_packet_decode(RADIUS_PACKET *packet)
 int fr_dhcpv4_packet_encode(RADIUS_PACKET *packet)
 {
        uint8_t         *p;
-       vp_cursor_t     cursor;
+       fr_cursor_t     cursor;
        VALUE_PAIR      *vp;
        uint32_t        lvalue;
        uint16_t        svalue;
@@ -485,13 +485,13 @@ int fr_dhcpv4_packet_encode(RADIUS_PACKET *packet)
         *  operates correctly. This changes the order of the list, but never mind...
         */
        fr_pair_list_sort(&packet->vps, fr_dhcpv4_attr_cmp);
-       fr_pair_cursor_init(&cursor, &packet->vps);
+       fr_cursor_init(&cursor, &packet->vps);
 
        /*
         *  Each call to fr_dhcpv4_encode_option will encode one complete DHCP option,
         *  and sub options.
         */
-       while ((vp = fr_pair_cursor_current(&cursor))) {
+       while ((vp = fr_cursor_current(&cursor))) {
                len = fr_dhcpv4_encode_option(p, packet->data_len - (p - packet->data), &cursor, NULL);
                if (len < 0) break;
                p += len;
diff --git a/src/protocols/dhcpv6/base.c b/src/protocols/dhcpv6/base.c
new file mode 100644 (file)
index 0000000..bead020
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ *   This library is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU Lesser General Public
+ *   License as published by the Free Software Foundation; either
+ *   version 2.1 of the License, or (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ *   Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ *
+ * @file protocols/dhcpv6/encode.c
+ * @brief Functions to encode DHCP options.
+ *
+ * @author Arran Cudbard-Bell <a.cudbardb@freeradius.org>
+ *
+ * @copyright 2018 The FreeRADIUS server project
+ * @copyright 2018 NetworkRADIUS SARL <info@networkradius.com>
+ */
+#include <stdint.h>
+#include <stddef.h>
+#include <talloc.h>
+#include <freeradius-devel/pair.h>
+#include <freeradius-devel/types.h>
+#include <freeradius-devel/proto.h>
+
+#include "dhcpv6.h"
+
+size_t const fr_dhcpv6_attr_sizes[FR_TYPE_MAX + 1][2] = {
+       [FR_TYPE_INVALID]               = {~0, 0},      //!< Ensure array starts at 0 (umm?)
+
+       [FR_TYPE_STRING]                = {0, ~0},
+       [FR_TYPE_OCTETS]                = {0, ~0},
+
+       [FR_TYPE_IPV4_ADDR]             = {4, 4},
+       [FR_TYPE_IPV4_PREFIX]           = {1, 5},       //!< Zero length prefix still requires one byte for prefix len.
+       [FR_TYPE_IPV6_ADDR]             = {16, 16},
+       [FR_TYPE_IPV6_PREFIX]           = {1, 17},      //!< Zero length prefix still requires one byte for prefix len.
+       [FR_TYPE_IFID]                  = {8, 8},
+       [FR_TYPE_ETHERNET]              = {6, 6},
+
+       [FR_TYPE_BOOL]                  = {1, 1},
+       [FR_TYPE_UINT8]                 = {1, 1},
+       [FR_TYPE_UINT16]                = {2, 2},
+       [FR_TYPE_UINT32]                = {4, 4},
+       [FR_TYPE_UINT64]                = {8, 8},
+
+       [FR_TYPE_TLV]                   = {2, ~0},
+       [FR_TYPE_STRUCT]                = {1, ~0},
+
+       [FR_TYPE_MAX]                   = {~0, 0}       //!< Ensure array covers all types.
+};
+
+/** Return the on-the-wire length of an attribute value
+ *
+ * @param[in] vp to return the length of.
+ * @return the length of the attribute.
+ */
+size_t fr_dhcpv6_option_len(VALUE_PAIR const *vp)
+{
+       switch (vp->vp_type) {
+       case FR_TYPE_VARIABLE_SIZE:
+               if (da->flags.length) return da->flags.length;  /* Variable type with fixed length */
+               return vp->vp_length;
+
+       default:
+               return fr_dhcpv6_attr_sizes[vp->vp_type][0];
+
+       case FR_TYPE_STRUCTURAL:
+               if (!fr_cond_assert(0)) return 0;
+       }
+}
index 0429f3d64cd56939fb169bec2ed529f7cba9873f..933fb3707671ae4257a571dfc452086f0dd597d5 100644 (file)
  */
 RCSIDH(dhcpv6_h, "$Id$")
 
+extern size_t const fr_dhcpv6_attr_sizes[FR_TYPE_MAX + 1][2];
+
+#define OPT_HDR_LEN    (sizeof(uint16_t) * 2)
+
+typedef struct {
+       fr_dict_attr_t const    *root;                          //!< Root attribute of the dictionary.
+} fr_dhcpv6_encode_ctx_t;
+
+/*
+ *     base.c
+ */
+size_t         fr_dhcpv6_option_len(VALUE_PAIR const *vp);
+
+/*
+ *     encode.c
+ */
 ssize_t                fr_dhcpv6_encode_option(uint8_t *out, size_t outlen, fr_cursor_t *cursor, void *encoder_ctx);
 
+/*
+ *     decode.c
+ */
 ssize_t                fr_dhcpv6_decode_option(TALLOC_CTX *ctx, vp_cursor_t *cursor,
                                        uint8_t const *data, size_t data_len, void *decoder_ctx);
 #endif
index 9538a4566de57139a825497a7caab886da136ce1..f455c6339458180f087f2a28fdb3642613cb3f02 100644 (file)
@@ -22,7 +22,7 @@
  *
  * @author Arran Cudbard-Bell <a.cudbardb@freeradius.org>
  *
- * @copyright 2018 The FreeRADIUS server project
+ * @copyright 2018 The freeradius server project
  * @copyright 2018 NetworkRADIUS SARL <info@networkradius.com>
  */
 #include <stdint.h>
 
 #include "dhcpv6.h"
 
-static ssize_t encode_tlv_hdr(UNUSED uint8_t *out, UNUSED size_t outlen,
-                             UNUSED fr_dict_attr_t const *tlv_stack[], UNUSED unsigned int depth, UNUSED fr_cursor_t *cursor)
+static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen,
+                             fr_dict_attr_t const **tlv_stack, unsigned int depth,
+                             fr_cursor_t *cursor, void *encoder_ctx);
+
+/** Find the next attribute to encode
+ *
+ * @param[in] cursor           to iterate over.
+ * @param[in] encoder_ctx      the context for the encoder.
+ * @return
+ *     - An encodable VALUE_PAIR.
+ *     - NULL if no encodable VALUE_PAIRs are available.
+ */
+static inline VALUE_PAIR *next_encodable(fr_cursor_t *cursor, void *encoder_ctx)
+{
+       VALUE_PAIR              *vp;
+       fr_dhcpv6_encode_ctx_t  *packet_ctx = encoder_ctx;
+
+       while ((vp = fr_cursor_next(cursor))) {
+               if (vp->da->flags.internal) continue;
+               if (fr_dict_parent_common(packet_ctx->root, vp->da, true)) break;
+       }
+
+       return vp;
+}
+
+/** Determine if the current attribute is encodable, or find the first one that is
+ *
+ * @param[in] cursor           to iterate over.
+ * @param[in] encoder_ctx      the context for the encoder.
+ * @return
+ *     - An encodable VALUE_PAIR.
+ *     - NULL if no encodable VALUE_PAIRs are available.
+ */
+/*
+static inline VALUE_PAIR *first_encodable(fr_cursor_t *cursor, void *encoder_ctx)
 {
-       return 0;
+       VALUE_PAIR              *vp;
+       fr_dhcpv6_encode_ctx_t  *packet_ctx = encoder_ctx;
+
+       vp = fr_cursor_current(cursor);
+       if (vp && !vp->da->flags.internal && fr_dict_parent_common(packet_ctx->root, vp->da, true)) return vp;
+
+       return next_encodable(cursor, encoder_ctx);
 }
+*/
 
-static ssize_t encode_rfc_hdr(UNUSED uint8_t *out, UNUSED size_t outlen,
-                             UNUSED fr_dict_attr_t const *tlv_stack[], UNUSED unsigned int depth, UNUSED fr_cursor_t *cursor)
+/** Macro-like function for encoding an option header
+ *
+ *    0                   1                   2                   3
+ *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |          option-code          |           option-len          |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * @param[out] out             Where to write the 4 byte option header.
+ * @param[in] outlen           Length of the output buffer.
+ * @param[in] option           The option number (host byte order).
+ * @param[in] data_len         The length of the option (host byte order).
+ * @return
+ *     - <0    How much data would have been required as a negative value.
+ *     - 4     The length of data written.
+ */
+static inline ssize_t encode_option_hdr(uint8_t *out, size_t outlen, uint16_t option, size_t data_len)
 {
-       return 0;
+       uint16_t        opt, len;
+       uint8_t         *p = out;
+
+       CHECK_FREESPACE(outlen, OPT_HDR_LEN);
+
+       opt = htons(option);
+       len = htons(data_len);
+
+       memcpy(p, &opt, sizeof(opt));
+       p += sizeof(opt);
+       memcpy(p, &len, sizeof(len));
+
+       return p - out;
+}
+
+static ssize_t encode_value(uint8_t *out, size_t outlen,
+                           fr_dict_attr_t const **tlv_stack, unsigned int depth,
+                           fr_cursor_t *cursor, void *encoder_ctx)
+{
+       ssize_t                 slen;
+       uint8_t                 *p = out, *end = p + outlen;
+       VALUE_PAIR const        *vp = fr_cursor_current(cursor);
+       fr_dict_attr_t const    *da = tlv_stack[depth];
+
+       VP_VERIFY(vp);
+       FR_PROTO_STACK_PRINT(tlv_stack, depth);
+
+       /*
+        *      Pack multiple attributes into into a single option
+        */
+//     if (da->type == FR_TYPE_STRUCT) {
+//             len = encode_struct(out, outlen, tlv_stack, depth, cursor, encoder_ctx);
+//             if (len < 0) return len;
+//
+//             vp = next_encodable(cursor);
+//             fr_proto_tlv_stack_build(tlv_stack, vp ? vp->da : NULL);
+//             return len;
+//     }
+
+       /*
+        *      If it's not a TLV, it should be a value type RFC
+        *      attribute make sure that it is.
+        */
+       if (tlv_stack[depth + 1] != NULL) {
+               fr_strerror_printf("%s: Encoding value but not at top of stack", __FUNCTION__);
+               return PAIR_ENCODE_ERROR;
+       }
+
+       if (vp->da != da) {
+               fr_strerror_printf("%s: Top of stack does not match vp->da", __FUNCTION__);
+               return PAIR_ENCODE_ERROR;
+       }
+
+       switch (da->type) {
+       case FR_TYPE_STRUCTURAL:
+               fr_strerror_printf("%s: Called with structural type %s", __FUNCTION__,
+                                  fr_int2str(dict_attr_types, tlv_stack[depth]->type, "?Unknown?"));
+               return PAIR_ENCODE_ERROR;
+
+       default:
+               break;
+       }
+
+
+       switch (da->type) {
+       /*
+        *    0                   1                   2                   3
+        *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *   |          option-code          |          option-len           |
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *   .                            String                             .
+        *   |                              ...                              |
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        */
+       case FR_TYPE_OCTETS:
+       case FR_TYPE_STRING:
+               /*
+                *      If asked to encode more data than allowed,
+                *      we encode only the allowed data.
+                */
+               slen = fr_dhcpv6_option_len(vp);
+               CHECK_FREESPACE(outlen, slen);
+
+               if (vp->vp_length < (size_t)slen) {
+                       memcpy(p, vp->vp_ptr, vp->vp_length);
+                       memset(p + vp->vp_length, 0, slen - vp->vp_length);
+               } else {
+                       memcpy(p, vp->vp_ptr, vp->vp_length);
+               }
+               p += slen;
+               break;
+
+       /*
+        * Common encoder might add scope byte, so we just copy the address portion
+        *
+        *    0                   1                   2                   3
+        *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *   |          option-code          |           option-len          |
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *   |                                                               |
+        *   |                         ipv6-address                          |
+        *   |                                                               |
+        *   |                                                               |
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        */
+       case FR_TYPE_IPV6_ADDR:
+               CHECK_FREESPACE(outlen, sizeof(vp->vp_ipv6addr));
+
+               memcpy(out, vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
+               p += sizeof(vp->vp_ipv6addr);
+               break;
+
+       /*
+        *      Common encoder doesn't add a reserved byte after prefix, but it also
+        *      doesn't do the variable length encoding required.
+        *
+        *      0                   1                   2                   3
+        *      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *     |          option-code          |         option-length         |
+        *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *     |  prefix6len   |              ipv6-prefix                      |
+        *     +-+-+-+-+-+-+-+-+           (variable length)                   |
+        *     .                                                               .
+        *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        */
+       case FR_TYPE_IPV6_PREFIX:
+       {
+               uint8_t prefix_len;
+
+               prefix_len = vp->vp_ip.prefix >> 3;             /* Convert bits to whole bytes */
+               CHECK_FREESPACE(outlen, prefix_len + 1);
+
+               *p++ = vp->vp_ip.prefix;
+               memcpy(p, &vp->vp_ipv6addr, prefix_len);        /* Only copy the minimum address bytes required */
+               p += prefix_len;
+       }
+               break;
+
+       /*
+        *      Not actually specified by the DHCPv6 RFC, but will probably come
+        *      in handy at some point if we need to have the DHCPv6 server
+        *      hand out v4 prefixes.
+        */
+       case FR_TYPE_IPV4_PREFIX:
+       {
+               uint8_t prefix_len;
+
+               prefix_len = vp->vp_ip.prefix >> 3;             /* Convert bits to whole bytes */
+               CHECK_FREESPACE(outlen, prefix_len + 1);
+
+               *p++ = vp->vp_ip.prefix;
+               memcpy(p, &vp->vp_ipv4addr, prefix_len);        /* Only copy the minimum address bytes required */
+               p += prefix_len;
+       }
+               break;
+
+       /*
+        *      Normal data types use the common encoder.
+        */
+       case FR_TYPE_IPV4_ADDR:
+       case FR_TYPE_IFID:
+       case FR_TYPE_ETHERNET:  /* just in case */
+
+       /*
+        *    0                   1                   2                   3
+        *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *   |          option-code          |           option-len          |
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        */
+       case FR_TYPE_BOOL:
+               return 0;       /* Bools are always true if present, so this is an empty option */
+
+       /*
+        *    0                   1                   2                   3
+        *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *   |          option-code          |          option-len           |
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *   | 8-bit-integer |
+        *   +-+-+-+-+-+-+-+-+
+        */
+       case FR_TYPE_UINT8:
+
+       /*
+        *    0                   1                   2                   3
+        *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *   |          option-code          |           option-len          |
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *   |         16-bit-integer        |
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        */
+       case FR_TYPE_UINT16:
+       /*
+        *    0                   1                   2                   3
+        *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *    |          option-code          |           option-len          |
+        *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *    |                         32-bit-integer                        |
+        *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        */
+       case FR_TYPE_UINT32:
+       case FR_TYPE_UINT64:
+       case FR_TYPE_INT8:
+       case FR_TYPE_INT16:
+       case FR_TYPE_INT32:
+       case FR_TYPE_INT64:
+       case FR_TYPE_DATE:
+               CHECK_FREESPACE(outlen, fr_dhcpv6_option_len(vp));
+               slen = fr_value_box_to_network(NULL, p, end - p, &vp->data);
+               if (slen < 0) return PAIR_ENCODE_ERROR;
+               p += slen;
+               break;
+
+       case FR_TYPE_INVALID:
+       case FR_TYPE_EXTENDED:
+       case FR_TYPE_LONG_EXTENDED:
+       case FR_TYPE_COMBO_IP_ADDR:     /* Should have been converted to concrete equivalent */
+       case FR_TYPE_COMBO_IP_PREFIX:   /* Should have been converted to concrete equivalent */
+       case FR_TYPE_EVS:
+       case FR_TYPE_VSA:
+       case FR_TYPE_VENDOR:
+       case FR_TYPE_TLV:
+       case FR_TYPE_STRUCT:
+       case FR_TYPE_SIZE:
+       case FR_TYPE_TIMEVAL:
+       case FR_TYPE_ABINARY:
+       case FR_TYPE_FLOAT32:
+       case FR_TYPE_FLOAT64:
+       case FR_TYPE_DATE_MILLISECONDS:
+       case FR_TYPE_DATE_MICROSECONDS:
+       case FR_TYPE_DATE_NANOSECONDS:
+       case FR_TYPE_VALUE_BOX:
+       case FR_TYPE_MAX:
+               fr_strerror_printf("Unsupported attribute type %d", da->type);
+               return PAIR_ENCODE_ERROR;
+       }
+
+       /*
+        *      Rebuilds the TLV stack for encoding the next attribute
+        */
+       vp = next_encodable(cursor, encoder_ctx);
+       fr_proto_tlv_stack_build(tlv_stack, vp ? vp->da : NULL);
+
+       return p - out;
+}
+
+static ssize_t encode_array(uint8_t *out, size_t outlen,
+                           fr_dict_attr_t const **tlv_stack, int depth,
+                           fr_cursor_t *cursor, void *encoder_ctx)
+{
+       uint8_t                 *p = out, *end = p + outlen;
+       ssize_t                 slen;
+       size_t                  element_len;
+       fr_dict_attr_t const    *da = tlv_stack[depth];
+
+       if (!fr_cond_assert_msg(da->flags.array,
+                               "%s: Internal sanity check failed, attribute \"%s\" does not have array bit set",
+                               __FUNCTION__, da->name)) return PAIR_ENCODE_ERROR;
+
+       while (p < end) {
+               uint16_t        *len_field;
+               VALUE_PAIR      *vp;
+
+               element_len = fr_dhcpv6_option_len(fr_cursor_current(cursor));
+
+               /*
+                *      If the data is variable length i.e. strings or octets
+                *      we need to include a length field before each element.
+                *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+
+                *   |       text-len                |        String                 |
+                *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+
+                */
+               if (!da->flags.length) {
+                       CHECK_FREESPACE(sizeof(uint16_t) + element_len, end - p);
+                       len_field = (uint16_t *)p;
+                       p += sizeof(uint16_t);                  /* Make room for the length field */
+               }
+
+               slen = encode_value(p, end - p, tlv_stack, depth, cursor, encoder_ctx);
+               if (slen < 0) return slen;
+               if (!fr_cond_assert(slen < UINT16_MAX)) return PAIR_ENCODE_ERROR;
+
+               /*
+                *      Ensure we always create elements of the correct length.
+                *      This is mainly for fixed length octets type attributes
+                *      containing one or more keys.
+                */
+               if (da->flags.length) {
+                       if ((size_t)slen < element_len) {
+                               memset(p + slen, 0, element_len - slen);
+                               slen = element_len;
+                       } else if ((size_t)slen > element_len){
+                               slen = element_len;
+                       }
+               }
+
+               p += slen;
+
+               /*
+                *      Populate the length field
+                */
+               if (!da->flags.length) *len_field = htons((uint16_t) slen);
+
+               vp = fr_cursor_current(cursor);
+               if (!vp || (vp->da != da)) break;               /* Stop if we have an attribute of a different type */
+       }
+
+       return p - out;
+}
+
+/** Encode an RFC format TLV.
+ *
+ * This could be a standard attribute, or a TLV data type.
+ * If it's a standard attribute, then vp->da->attr == attribute.
+ * Otherwise, attribute may be something else.
+ */
+static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen,
+                             fr_dict_attr_t const **tlv_stack, unsigned int depth,
+                             fr_cursor_t *cursor, void *encoder_ctx)
+{
+       uint8_t                 *p = out, *end = p + outlen;
+       ssize_t                 slen;
+       fr_dict_attr_t const    *da;
+
+       FR_PROTO_STACK_PRINT(tlv_stack, depth);
+
+       da = tlv_stack[depth];
+
+       switch (da->type) {
+       case FR_TYPE_STRUCTURAL:
+               fr_strerror_printf("%s: Called with structural type %s", __FUNCTION__,
+                                  fr_int2str(dict_attr_types, da->type, "?Unknown?"));
+               return PAIR_ENCODE_ERROR;
+
+       default:
+               if (((da->vendor == 0) && (da->attr == 0)) || (da->attr > UINT16_MAX)) {
+                       fr_strerror_printf("%s: Called with non-standard attribute %u", __FUNCTION__,
+                                          tlv_stack[depth]->attr);
+                       return PAIR_ENCODE_ERROR;
+               }
+               break;
+       }
+
+       CHECK_FREESPACE(outlen, OPT_HDR_LEN);
+
+       /*
+        *      Make space for the header...
+        */
+       p += OPT_HDR_LEN;
+
+       /*
+        *      Write out the option's value
+        */
+       if (da->flags.array) {
+               slen = encode_array(p, end - p, tlv_stack, depth, cursor, encoder_ctx);
+       } else {
+               slen = encode_value(p, end - p, tlv_stack, depth, cursor, encoder_ctx);
+       }
+       if (slen < 0) return slen;
+       p += slen;
+
+       /*
+        *      Write out the option number and length (before the value we jus wrote)
+        */
+       slen = encode_option_hdr(out, outlen, (uint16_t)tlv_stack[depth]->attr, (uint16_t)slen);
+       if (slen < 0) return slen;
+
+#ifndef NDEBUG
+       FR_PROTO_HEX_DUMP("Done RFC header", out, p - out);
+#endif
+
+       return p - out;
+}
+
+static inline ssize_t encode_tlv_internal(uint8_t *out, size_t outlen,
+                                         fr_dict_attr_t const **tlv_stack, unsigned int depth,
+                                         fr_cursor_t *cursor, void *encoder_ctx)
+{
+       ssize_t                 slen;
+       uint8_t                 *p = out, *end = p + outlen, *value;
+       VALUE_PAIR const        *vp = fr_cursor_current(cursor);
+       fr_dict_attr_t const    *da = tlv_stack[depth];
+
+       CHECK_FREESPACE(outlen, OPT_HDR_LEN);
+
+       while ((size_t)(end - p) > OPT_HDR_LEN) {
+               FR_PROTO_STACK_PRINT(tlv_stack, depth);
+
+               /*
+                *      Determine the nested type and call the appropriate encoder
+                */
+               if (tlv_stack[depth + 1]->type == FR_TYPE_TLV) {
+                       slen = encode_tlv_hdr(p, end - p, tlv_stack, depth + 1, cursor, encoder_ctx);
+               } else {
+                       slen = encode_rfc_hdr(p, end - p, tlv_stack, depth + 1, cursor, encoder_ctx);
+               }
+               if (slen < 0) return slen;
+
+               p += slen;
+
+               /*
+                *      If nothing updated the attribute, stop
+                */
+               if (!fr_cursor_current(cursor) || (vp == fr_cursor_current(cursor))) break;
+
+               /*
+                *      We can encode multiple sub TLVs, if after
+                *      rebuilding the TLV Stack, the attribute
+                *      at this depth is the same.
+                */
+               if (da != tlv_stack[depth]) break;
+               vp = fr_cursor_current(cursor);
+       }
+
+#ifndef NDEBUG
+       FR_PROTO_HEX_DUMP("Done TLV body", out, p - out);
+#endif
+
+       return p - out;
+}
+
+static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen,
+                             fr_dict_attr_t const **tlv_stack, unsigned int depth,
+                             fr_cursor_t *cursor, void *encoder_ctx)
+{
+       ssize_t                 slen;
+       uint8_t                 *p = out, *end = p + outlen;
+       fr_dict_attr_t const    *da;
+
+       VP_VERIFY(fr_cursor_current(cursor));
+       FR_PROTO_STACK_PRINT(tlv_stack, depth);
+
+       if (tlv_stack[depth]->type != FR_TYPE_TLV) {
+               fr_strerror_printf("%s: Expected type \"tlv\" got \"%s\"", __FUNCTION__,
+                                  fr_int2str(dict_attr_types, tlv_stack[depth]->type, "?Unknown?"));
+               return PAIR_ENCODE_ERROR;
+       }
+
+       if (!tlv_stack[depth + 1]) {
+               fr_strerror_printf("%s: Can't encode empty TLV", __FUNCTION__);
+               return PAIR_ENCODE_ERROR;
+       }
+
+       CHECK_FREESPACE(outlen, OPT_HDR_LEN);
+
+       da = tlv_stack[depth];  /* Remember this, stack might change */
+
+       p += OPT_HDR_LEN;       /* Make room for option header */
+       slen = encode_tlv_internal(p, end - p, tlv_stack, depth, cursor, encoder_ctx);
+       if (slen < 0) return slen;
+       p += slen;
+
+       /*
+        *    0                   1                   2                   3
+        *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *   |          option-code          |           option-len          |
+        *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        */
+       slen = encode_option_hdr(out, outlen, (uint16_t)da->attr, (uint16_t)slen);
+       if (slen < 0) return slen;
+
+#ifndef NDEBUG
+       FR_PROTO_HEX_DUMP("Done TLV header", out, p - out);
+#endif
+
+       return p - out;
+}
+
+/** Encode a VSIO (Vendor Specific Information Opion)
+ *
+ * If it's in the RFC format, call encode_rfc_hdr.  Otherwise, encode it here.
+ * This allows variable length vendor options.  There is no specific format
+ * specified for vendor option data, so we need to allow for variable width
+ * option fields and length field widths.
+ *
+ *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     .                                                               .
+ *     .                          option-data                          .
+ *     .                                                               .
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+static ssize_t encode_vendor_attr_hdr(uint8_t *out, size_t outlen,
+                                     fr_dict_attr_t const **tlv_stack, unsigned int depth,
+                                     fr_cursor_t *cursor, void *encoder_ctx)
+{
+       ssize_t                 slen;
+       uint8_t                 *p = out, *end = p + outlen, *len_field;
+       size_t                  hdr_len;
+       fr_dict_attr_t const    *da, *dv;
+
+       FR_PROTO_STACK_PRINT(tlv_stack, depth);
+
+       /*
+        *      This is the dictionary attribute which contains the
+        *      vendor IANA ID.
+        */
+       dv = tlv_stack[depth++];
+       if (dv->type != FR_TYPE_VENDOR) {
+               fr_strerror_printf("Expected Vendor");
+               return PAIR_ENCODE_ERROR;
+       }
+
+       da = tlv_stack[depth];
+
+       /*
+        *      If the option field size is 1 byte, we can just
+        *      encode it as a standard option header.
+        */
+       if ((da->type != FR_TYPE_TLV) &&
+           (dv->flags.type_size == 1) &&
+           (dv->flags.length == 1)) return encode_rfc_hdr(out, outlen, tlv_stack, depth, cursor, encoder_ctx);
+
+       hdr_len = dv->flags.type_size + dv->flags.length;
+       CHECK_FREESPACE(end - p, hdr_len);
+
+       /*
+        *      Vendors use different widths for their option
+        *      number fields.
+        */
+       switch (dv->flags.type_size) {
+       default:
+               fr_strerror_printf("%s: Internal sanity check failed, type %u", __FUNCTION__,
+                                  (unsigned) dv->flags.type_size);
+               return PAIR_ENCODE_ERROR;
+
+       case 4: /* 32bit */
+               *p++ = (da->attr >> 24) & 0xff;
+               *p++ = (da->attr >> 16) & 0xff;
+               *p++ = (da->attr >> 8) & 0xff;
+               *p++ = (da->attr & 0xff);
+               break;
+
+       case 3: /* 24bit */
+               *p++ = (da->attr >> 16) & 0xff;
+               *p++ = (da->attr >> 8) & 0xff;
+               *p++ = (da->attr & 0xff);
+               break;
+
+       case 2: /* 16bit */
+               *p++ = (da->attr >> 8) & 0xff;
+               *p++ = (da->attr & 0xff);
+               break;
+
+       case 1: /* 8 bit */
+               *p++ = (da->attr & 0xff);
+               break;
+       }
+
+       switch (dv->flags.length) {
+       default:
+               fr_strerror_printf("%s: Internal sanity check failed, length %u",
+                                  __FUNCTION__, (unsigned) dv->flags.length);
+               return PAIR_ENCODE_ERROR;
+
+       case 0: /* No length field ??? */
+               break;
+
+       case 2: /* 16bit length field */
+               len_field = p;
+               p += sizeof(uint16_t);
+               break;
+
+       case 1: /* 8bit length field */
+               len_field = p;
+               p += sizeof(uint8_t);
+               break;
+       }
+
+       /*
+        *      Because we've now encoded the attribute header,
+        *      if this is a TLV, we must process it via the
+        *      internal tlv function, else we get a double TLV header.
+        */
+       if (da->type == FR_TYPE_TLV) {
+               slen = encode_tlv_internal(p, end - p, tlv_stack, depth, cursor, encoder_ctx);
+       /*
+        *      Array of values inside a vendor option
+        */
+       } else if (da->flags.array) {
+               slen = encode_array(p, end - p, tlv_stack, depth, cursor, encoder_ctx);
+       /*
+        *      Normal vendor option
+        */
+       } else {
+               slen = encode_value(p, end - p, tlv_stack, depth, cursor, encoder_ctx);
+       }
+       if (slen < 0) return slen;
+       p += slen;
+
+       switch (dv->flags.length) {
+       default:
+               break;
+
+       case 2:
+               len_field[0] = ((end - p) >> 8) & 0xff;
+               len_field[1] = (end - p) & 0xff;
+               break;
+
+       case 1:
+               len_field[0] = (end - p) & 0xff;
+               break;
+       }
+
+#ifndef NDEBUG
+       FR_PROTO_HEX_DUMP("Done VSIO body", out, end - p);
+#endif
+
+       return p - out;
+}
+
+/** Encode a Vendor-Specific Information Option
+ *
+ *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |      OPTION_VENDOR_OPTS       |           option-len          |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |                       enterprise-number                       |
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     .                                                               .
+ *     .                          option-data                          .
+ *     .                                                               .
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+static ssize_t encode_vsio_hdr(uint8_t *out, size_t outlen,
+                              fr_dict_attr_t const **tlv_stack, unsigned int depth,
+                              fr_cursor_t *cursor, void *encoder_ctx)
+{
+       ssize_t                 slen;
+       uint32_t                pen;
+       uint8_t                 *p = out, *end = p + outlen;
+       fr_dict_attr_t const    *da = tlv_stack[depth];
+
+       FR_PROTO_STACK_PRINT(tlv_stack, depth);
+
+       /*
+        *      DA should be a VSA type with the value of OPTION_VENDOR_OPTS.
+        */
+       if (da->type != FR_TYPE_VSA) {
+               fr_strerror_printf("%s: Expected type \"vsa\" got \"%s\"", __FUNCTION__,
+                                  fr_int2str(dict_attr_types, da->type, "?Unknown?"));
+               return PAIR_ENCODE_ERROR;
+       }
+
+       /*
+        *      Check if we have enough for an option header plus the
+        *      enterprise-number.
+        */
+       CHECK_FREESPACE(outlen, OPT_HDR_LEN + sizeof(uint32_t));
+
+       /*
+        *      Now process the vendor ID part (which is one attribute deeper)
+        */
+       da = tlv_stack[++depth];
+       FR_PROTO_STACK_PRINT(tlv_stack, depth);
+
+       if (da->type != FR_TYPE_VENDOR) {
+               fr_strerror_printf("%s: Expected type \"vsa\" got \"%s\"", __FUNCTION__,
+                                  fr_int2str(dict_attr_types, da->type, "?Unknown?"));
+               return PAIR_ENCODE_ERROR;
+       }
+
+       /*
+        *      Copy in the 32bit PEN (Private Enterprise Number)
+        */
+       p += OPT_HDR_LEN;
+       pen = htonl(da->attr);
+       memcpy(p, &pen, sizeof(pen));
+
+       /*
+        *      Encode the vendor specific option header
+        *      i.e. OPTION_VENDOR_OPTS and whatever the length of the vendor
+        *      specific attribute was.
+        */
+       slen = encode_vendor_attr_hdr(p, end - p, tlv_stack, depth, cursor, encoder_ctx);
+       if (slen < 0) return slen;
+       p += slen;
+
+       encode_option_hdr(out, outlen, da->attr, p - out);
+
+#ifndef NDEBUG
+       FR_PROTO_HEX_DUMP("Done VSIO header", out, end - p);
+#endif
+
+       return p - out;
 }
 
 /** Encode a DHCPv6 option and any sub-options.
  *
- * @param[out] out Where to write encoded DHCP attributes.
- * @param[in] outlen Length of out buffer.
- * @param[in] cursor with current VP set to the option to be encoded. Will be advanced to the next option to encode.
- * @param[in] encoder_ctx containing parameters for the encoder.
+ * @param[out] out             Where to write encoded DHCP attributes.
+ * @param[in] outlen           Length of out buffer.
+ * @param[in] cursor           with current VP set to the option to be encoded.
+ *                             Will be advanced to the next option to encode.
+ * @param[in] encoder_ctx      containing parameters for the encoder.
  * @return
  *     - > 0 length of data written.
  *     - < 0 error.
- *     - 0 not valid option for DHCP (skipping).
  */
-ssize_t fr_dhcpv6_encode_option(uint8_t *out, size_t outlen, fr_cursor_t *cursor, UNUSED void *encoder_ctx)
+ssize_t fr_dhcpv6_encode_option(uint8_t *out, size_t outlen, fr_cursor_t *cursor, void *encoder_ctx)
 {
        VALUE_PAIR              *vp;
        unsigned int            depth = 0;
        fr_dict_attr_t const    *tlv_stack[FR_DICT_MAX_TLV_STACK + 1];
-       ssize_t                 len;
+       ssize_t                 slen;
 
        vp = fr_cursor_current(cursor);
-       if (!vp) return -1;
+       if (!vp) return PAIR_ENCODE_ERROR;
 
        if (vp->da->flags.internal) {
                fr_strerror_printf("Attribute \"%s\" is not a DHCPv6 option", vp->da->name);
                fr_cursor_next(cursor);
-               return 0;
+               return PAIR_ENCODE_SKIP;
        }
 
        fr_proto_tlv_stack_build(tlv_stack, vp->da);
@@ -80,22 +826,31 @@ ssize_t fr_dhcpv6_encode_option(uint8_t *out, size_t outlen, fr_cursor_t *cursor
        FR_PROTO_STACK_PRINT(tlv_stack, depth);
 
        /*
-        *      We only have two types of options in DHCPv6
+        *      Trim output buffer size for sanity
+        */
+       if (outlen > (OPT_HDR_LEN + UINT16_MAX)) outlen = (OPT_HDR_LEN + UINT16_MAX);
+
+       /*
+        *      Deal with nested options
         */
        switch (tlv_stack[depth]->type) {
        case FR_TYPE_TLV:
-               len = encode_tlv_hdr(out, outlen, tlv_stack, depth, cursor);
+               slen = encode_tlv_hdr(out, outlen, tlv_stack, depth, cursor, encoder_ctx);
+               break;
+
+       case FR_TYPE_VSA:
+               slen = encode_vsio_hdr(out, outlen, tlv_stack, depth, cursor, encoder_ctx);
                break;
 
        default:
-               len = encode_rfc_hdr(out, outlen, tlv_stack, depth, cursor);
+               slen = encode_rfc_hdr(out, outlen, tlv_stack, depth, cursor, encoder_ctx);
                break;
        }
 
-       if (len < 0) return len;
+       if (slen <= 0) return slen;
 
-       FR_PROTO_TRACE("Complete option is %zu byte(s)", len);
-       FR_PROTO_HEX_DUMP(NULL, out, len);
+       FR_PROTO_TRACE("Complete option is %zu byte(s)", slen);
+       FR_PROTO_HEX_DUMP(NULL, out, slen);
 
-       return len;
+       return slen;
 }
index 6b0a337a54f02372237a55881d5ffc357c73653e..cbd564484fb9b29a661749f6bee7c371fd3aa784 100644 (file)
@@ -824,7 +824,7 @@ ssize_t fr_radius_encode(uint8_t *packet, size_t packet_len, uint8_t const *orig
        int                     total_length;
        int                     len;
        VALUE_PAIR const        *vp;
-       vp_cursor_t             cursor;
+       fr_cursor_t             cursor;
        fr_radius_ctx_t         packet_ctx;
 
        packet_ctx.secret = secret;
@@ -912,8 +912,8 @@ ssize_t fr_radius_encode(uint8_t *packet, size_t packet_len, uint8_t const *orig
        /*
         *      Loop over the reply attributes for the packet.
         */
-       fr_pair_cursor_init(&cursor, &vps);
-       while ((vp = fr_pair_cursor_current(&cursor))) {
+       fr_cursor_init(&cursor, &vps);
+       while ((vp = fr_cursor_current(&cursor))) {
                size_t          last_len, room;
                char const      *last_name = NULL;
 
@@ -942,11 +942,11 @@ ssize_t fr_radius_encode(uint8_t *packet, size_t packet_len, uint8_t const *orig
                                }
 
                                memcpy(ptr, vp->vp_octets, len);
-                               fr_pair_cursor_next(&cursor);
+                               fr_cursor_next(&cursor);
                                goto next;
                        }
 #endif
-                       fr_pair_cursor_next(&cursor);
+                       fr_cursor_next(&cursor);
                        continue;
                }
 
@@ -1007,7 +1007,7 @@ ssize_t   fr_radius_decode(TALLOC_CTX *ctx, uint8_t *packet, size_t packet_len, ui
                         char const *secret, UNUSED size_t secret_len, VALUE_PAIR **vps)
 {
        ssize_t                 slen;
-       vp_cursor_t             cursor;
+       fr_cursor_t             cursor;
        uint8_t const           *attr, *end;
        fr_radius_ctx_t         packet_ctx;
 
@@ -1015,7 +1015,7 @@ ssize_t   fr_radius_decode(TALLOC_CTX *ctx, uint8_t *packet, size_t packet_len, ui
        packet_ctx.vector = original + 4;
        packet_ctx.root = fr_dict_root(fr_dict_internal);
 
-       fr_pair_cursor_init(&cursor, vps);
+       fr_cursor_init(&cursor, vps);
 
        attr = packet + 20;
        end = packet + packet_len;
index 0de8b94491428172137738b3c42f28f7eb4eda6c..c718316ea29ef9fb128941a28bdfe732a75881b8 100644 (file)
@@ -327,7 +327,7 @@ int fr_radius_decode_tlv_ok(uint8_t const *data, size_t length, size_t dv_type,
 /** Convert a "concatenated" attribute to one long VP
  *
  */
-static ssize_t decode_concat(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+static ssize_t decode_concat(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                             fr_dict_attr_t const *parent, uint8_t const *data,
                             size_t const packet_len)
 {
@@ -387,7 +387,7 @@ static ssize_t decode_concat(TALLOC_CTX *ctx, vp_cursor_t *cursor,
                p += ptr[1] - 2;
                ptr += ptr[1];
        }
-       fr_pair_cursor_append(cursor, vp);
+       fr_cursor_append(cursor, vp);
        return ptr - data;
 }
 
@@ -395,14 +395,14 @@ static ssize_t decode_concat(TALLOC_CTX *ctx, vp_cursor_t *cursor,
 /** Convert TLVs to one or more VPs
  *
  */
-ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                             fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len,
                             void *decoder_ctx)
 {
        uint8_t const           *p = data, *end = data + data_len;
        fr_dict_attr_t const    *child;
        VALUE_PAIR              *head = NULL;
-       vp_cursor_t             tlv_cursor;
+       fr_cursor_t             tlv_cursor;
 
        if (data_len < 3) return -1; /* type, length, value */
 
@@ -413,7 +413,7 @@ ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor,
        /*
         *  Record where we were in the list when this function was called
         */
-       fr_pair_cursor_init(&tlv_cursor, &head);
+       fr_cursor_init(&tlv_cursor, &head);
        while (p < end) {
                ssize_t tlv_len;
 
@@ -440,7 +440,9 @@ ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor,
                if (tlv_len < 0) goto error;
                p += p[1];
        }
-       fr_pair_cursor_merge(cursor, head);     /* Wind to the end of the new pairs */
+       fr_cursor_head(&tlv_cursor);
+       fr_cursor_tail(cursor);
+       fr_cursor_merge(cursor, &tlv_cursor);   /* Wind to the end of the new pairs */
 
        return data_len;
 }
@@ -448,7 +450,7 @@ ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor,
 /** Convert a STRUCT to one or more VPs
  *
  */
-static ssize_t fr_radius_decode_struct(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+static ssize_t fr_radius_decode_struct(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                                       fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len,
                                       void *decoder_ctx)
 {
@@ -456,7 +458,7 @@ static ssize_t fr_radius_decode_struct(TALLOC_CTX *ctx, vp_cursor_t *cursor,
        uint8_t const           *p = data, *end = data + data_len;
        fr_dict_attr_t const    *child;
        VALUE_PAIR              *head = NULL;
-       vp_cursor_t             child_cursor;
+       fr_cursor_t             child_cursor;
 
        if (data_len < 1) return -1; /* at least one byte of data */
 
@@ -467,7 +469,7 @@ static ssize_t fr_radius_decode_struct(TALLOC_CTX *ctx, vp_cursor_t *cursor,
        /*
         *  Record where we were in the list when this function was called
         */
-       fr_pair_cursor_init(&child_cursor, &head);
+       fr_cursor_init(&child_cursor, &head);
        child_num = 1;
        while (p < end) {
                ssize_t child_len;
@@ -492,7 +494,7 @@ static ssize_t fr_radius_decode_struct(TALLOC_CTX *ctx, vp_cursor_t *cursor,
 
                raw:
                        fr_pair_list_free(&head);
-                       fr_pair_cursor_init(&child_cursor, &head);
+                       fr_cursor_init(&child_cursor, &head);
 
                        /*
                         *      Build an unknown attr of the entire STRUCT.
@@ -511,7 +513,9 @@ static ssize_t fr_radius_decode_struct(TALLOC_CTX *ctx, vp_cursor_t *cursor,
                p += child->flags.length;
                child_num++;    /* go to the next child */
        }
-       fr_pair_cursor_merge(cursor, head);     /* Wind to the end of the new pairs */
+       fr_cursor_head(&child_cursor);
+       fr_cursor_tail(cursor);
+       fr_cursor_merge(cursor, &child_cursor); /* Wind to the end of the new pairs */
 
        return data_len;
 }
@@ -520,7 +524,7 @@ static ssize_t fr_radius_decode_struct(TALLOC_CTX *ctx, vp_cursor_t *cursor,
  *
  * "length" can be LONGER than just this sub-vsa.
  */
-static ssize_t decode_vsa_internal(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+static ssize_t decode_vsa_internal(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                                   fr_dict_attr_t const *parent,
                                   uint8_t const *data, size_t data_len,
                                   void *decoder_ctx, fr_dict_vendor_t const *dv)
@@ -616,7 +620,7 @@ static ssize_t decode_vsa_internal(TALLOC_CTX *ctx, vp_cursor_t *cursor,
  *
  * But for the first fragment, we get passed a pointer to the "extended-attr"
  */
-static ssize_t decode_extended(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+static ssize_t decode_extended(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                               fr_dict_attr_t const *parent,
                               uint8_t const *data, size_t attr_len, size_t packet_len,
                               void *decoder_ctx)
@@ -706,7 +710,7 @@ static ssize_t decode_extended(TALLOC_CTX *ctx, vp_cursor_t *cursor,
  *
  * @note Called ONLY for Vendor-Specific
  */
-static ssize_t decode_wimax(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+static ssize_t decode_wimax(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                            fr_dict_attr_t const *parent,
                            uint8_t const *data, size_t attr_len, size_t packet_len, void *decoder_ctx, uint32_t vendor)
 {
@@ -868,7 +872,7 @@ static ssize_t decode_wimax(TALLOC_CTX *ctx, vp_cursor_t *cursor,
 /** Convert a top-level VSA to one or more VPs
  *
  */
-static ssize_t decode_vsa(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent,
+static ssize_t decode_vsa(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_attr_t const *parent,
                          uint8_t const *data, size_t attr_len, size_t packet_len,
                          void *decoder_ctx)
 {
@@ -879,7 +883,7 @@ static ssize_t decode_vsa(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t c
        VALUE_PAIR              *head = NULL;
        fr_dict_vendor_t        my_dv;
        fr_dict_attr_t const    *vendor_da;
-       vp_cursor_t             tlv_cursor;
+       fr_cursor_t             tlv_cursor;
 
        /*
         *      Container must be a VSA
@@ -965,7 +969,7 @@ create_attrs:
        packet_len -= 4;
        total = 4;
 
-       fr_pair_cursor_init(&tlv_cursor, &head);
+       fr_cursor_init(&tlv_cursor, &head);
        while (attr_len > 0) {
                ssize_t vsa_len;
 
@@ -985,7 +989,9 @@ create_attrs:
                packet_len -= vsa_len;
                total += vsa_len;
        }
-       fr_pair_cursor_merge(cursor, head);
+       fr_cursor_head(&tlv_cursor);
+       fr_cursor_tail(cursor);
+       fr_cursor_merge(cursor, &tlv_cursor);
 
        /*
         *      When the unknown attributes were created by
@@ -1009,7 +1015,7 @@ create_attrs:
  *     - Length on success.
  *     - -1 on failure.
  */
-ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent,
+ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_attr_t const *parent,
                                    uint8_t const *data, size_t const attr_len, size_t const packet_len,
                                    void *decoder_ctx)
 {
@@ -1490,7 +1496,7 @@ ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dic
        }
        vp->type = VT_DATA;
        vp->vp_tainted = true;
-       fr_pair_cursor_append(cursor, vp);
+       fr_cursor_append(cursor, vp);
 
        return attr_len;
 }
@@ -1499,7 +1505,7 @@ ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dic
 /** Create a "normal" VALUE_PAIR from the given data
  *
  */
-ssize_t fr_radius_decode_pair(TALLOC_CTX *ctx, vp_cursor_t *cursor,
+ssize_t fr_radius_decode_pair(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                              uint8_t const *data, size_t data_len, void *decoder_ctx)
 {
        ssize_t                 rcode;
@@ -1540,7 +1546,7 @@ ssize_t fr_radius_decode_pair(TALLOC_CTX *ctx, vp_cursor_t *cursor,
                 */
                vp = fr_pair_afrom_da(ctx, da);
                if (!vp) return -1;
-               fr_pair_cursor_append(cursor, vp);
+               fr_cursor_append(cursor, vp);
                vp->vp_tainted = true;          /* not REALLY necessary, but what the heck */
 
                return 2;
index 30f5c53f05a5f9e5ee1b61ac26dee74b3423e621..e3e198dd792159f62d9d3c95c4849e5c86c81731 100644 (file)
@@ -32,15 +32,15 @@ static unsigned int salt_offset = 0;
 
 static ssize_t encode_value(uint8_t *out, size_t outlen,
                            fr_dict_attr_t const **tlv_stack, int depth,
-                           vp_cursor_t *cursor, void *encoder_ctx);
+                           fr_cursor_t *cursor, void *encoder_ctx);
 
 static ssize_t encode_rfc_hdr_internal(uint8_t *out, size_t outlen,
                                       fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                                      vp_cursor_t *cursor, void *encoder_ctx);
+                                      fr_cursor_t *cursor, void *encoder_ctx);
 
 static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen,
                              fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                             vp_cursor_t *cursor, void *encoder_ctx);
+                             fr_cursor_t *cursor, void *encoder_ctx);
 
 
 /** Determine if the current attribute is encodable, or find the first one that is
@@ -48,12 +48,12 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen,
  * @param cursor to iterate over.
  * @return encodable VALUE_PAIR, or NULL if none available.
  */
-static inline VALUE_PAIR *first_encodable(vp_cursor_t *cursor)
+static inline VALUE_PAIR *first_encodable(fr_cursor_t *cursor)
 {
        VALUE_PAIR *vp;
 
-       for (vp = fr_pair_cursor_current(cursor); vp && vp->da->flags.internal; vp = fr_pair_cursor_next(cursor));
-       return fr_pair_cursor_current(cursor);
+       for (vp = fr_cursor_current(cursor); vp && vp->da->flags.internal; vp = fr_cursor_next(cursor));
+       return fr_cursor_current(cursor);
 }
 
 /** Find the next attribute to encode
@@ -61,16 +61,16 @@ static inline VALUE_PAIR *first_encodable(vp_cursor_t *cursor)
  * @param cursor to iterate over.
  * @return encodable VALUE_PAIR, or NULL if none available.
  */
-static inline VALUE_PAIR *next_encodable(vp_cursor_t *cursor)
+static inline VALUE_PAIR *next_encodable(fr_cursor_t *cursor)
 {
        VALUE_PAIR *vp;
 
        for (;;) {
-               vp = fr_pair_cursor_next(cursor);
+               vp = fr_cursor_next(cursor);
                if (!vp || !vp->da->flags.internal) break;
        }
 
-       return fr_pair_cursor_current(cursor);
+       return fr_cursor_current(cursor);
 }
 
 /** Encode a CHAP password
@@ -412,15 +412,15 @@ static void encode_tunnel_password(uint8_t *out, ssize_t *outlen,
 
 static ssize_t encode_struct(uint8_t *out, size_t outlen,
                              fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                             vp_cursor_t *cursor, void *encoder_ctx)
+                             fr_cursor_t *cursor, void *encoder_ctx)
 {
        ssize_t                 len;
        unsigned int            child_num = 1;
        uint8_t                 *p = out;
-       VALUE_PAIR const        *vp = fr_pair_cursor_current(cursor);
+       VALUE_PAIR const        *vp = fr_cursor_current(cursor);
        fr_dict_attr_t const    *da = tlv_stack[depth];
 
-       VP_VERIFY(fr_pair_cursor_current(cursor));
+       VP_VERIFY(fr_cursor_current(cursor));
        FR_PROTO_STACK_PRINT(tlv_stack, depth);
 
        if (tlv_stack[depth]->type != FR_TYPE_STRUCT) {
@@ -475,7 +475,7 @@ static ssize_t encode_struct(uint8_t *out, size_t outlen,
                /*
                 *      If nothing updated the attribute, stop
                 */
-               if (!fr_pair_cursor_current(cursor) || (vp == fr_pair_cursor_current(cursor))) break;
+               if (!fr_cursor_current(cursor) || (vp == fr_cursor_current(cursor))) break;
 
                /*
                 *      We can encode multiple sub TLVs, if after
@@ -483,7 +483,7 @@ static ssize_t encode_struct(uint8_t *out, size_t outlen,
                 *      at this depth is the same.
                 */
                if (da != tlv_stack[depth]) break;
-               vp = fr_pair_cursor_current(cursor);
+               vp = fr_cursor_current(cursor);
 
                FR_PROTO_HEX_DUMP("Done STRUCT", out, p - out);
        }
@@ -493,11 +493,11 @@ static ssize_t encode_struct(uint8_t *out, size_t outlen,
 
 static ssize_t encode_tlv_hdr_internal(uint8_t *out, size_t outlen,
                                       fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                                      vp_cursor_t *cursor, void *encoder_ctx)
+                                      fr_cursor_t *cursor, void *encoder_ctx)
 {
        ssize_t                 len;
        uint8_t                 *p = out;
-       VALUE_PAIR const        *vp = fr_pair_cursor_current(cursor);
+       VALUE_PAIR const        *vp = fr_cursor_current(cursor);
        fr_dict_attr_t const    *da = tlv_stack[depth];
 
        while (outlen >= 5) {
@@ -528,7 +528,7 @@ static ssize_t encode_tlv_hdr_internal(uint8_t *out, size_t outlen,
                /*
                 *      If nothing updated the attribute, stop
                 */
-               if (!fr_pair_cursor_current(cursor) || (vp == fr_pair_cursor_current(cursor))) break;
+               if (!fr_cursor_current(cursor) || (vp == fr_cursor_current(cursor))) break;
 
                /*
                 *      We can encode multiple sub TLVs, if after
@@ -536,7 +536,7 @@ static ssize_t encode_tlv_hdr_internal(uint8_t *out, size_t outlen,
                 *      at this depth is the same.
                 */
                if (da != tlv_stack[depth]) break;
-               vp = fr_pair_cursor_current(cursor);
+               vp = fr_cursor_current(cursor);
 
                FR_PROTO_HEX_DUMP("Done TLV", out, p - out);
        }
@@ -546,11 +546,11 @@ static ssize_t encode_tlv_hdr_internal(uint8_t *out, size_t outlen,
 
 static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen,
                              fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                             vp_cursor_t *cursor, void *encoder_ctx)
+                             fr_cursor_t *cursor, void *encoder_ctx)
 {
        ssize_t                 len;
 
-       VP_VERIFY(fr_pair_cursor_current(cursor));
+       VP_VERIFY(fr_cursor_current(cursor));
        FR_PROTO_STACK_PRINT(tlv_stack, depth);
 
        if (tlv_stack[depth]->type != FR_TYPE_TLV) {
@@ -591,14 +591,14 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen,
  */
 static ssize_t encode_value(uint8_t *out, size_t outlen,
                            fr_dict_attr_t const **tlv_stack, int depth,
-                           vp_cursor_t *cursor, void *encoder_ctx)
+                           fr_cursor_t *cursor, void *encoder_ctx)
 {
        size_t                  offset;
        ssize_t                 len;
        uint8_t const           *data = NULL;
        uint8_t                 *ptr = out;
        uint8_t                 buffer[64];
-       VALUE_PAIR const        *vp = fr_pair_cursor_current(cursor);
+       VALUE_PAIR const        *vp = fr_cursor_current(cursor);
        fr_dict_attr_t const    *da = tlv_stack[depth];
        fr_radius_ctx_t         *packet_ctx = encoder_ctx;
 
@@ -655,17 +655,13 @@ static ssize_t encode_value(uint8_t *out, size_t outlen,
        len = fr_radius_attr_len(vp);
 
        switch (da->type) {
+       /*
+        *      If asked to encode more data than allowed, we
+        *      encode only the allowed data.
+        */
        case FR_TYPE_OCTETS:
-               /*
-                *      If asked to encode more data than allowed, we
-                *      encode only the allowed data.
-                */
-               if (da->flags.length && (len > da->flags.length)) {
-                       len = da->flags.length;
-               }
-               /* FALL-THROUGH */
-
        case FR_TYPE_STRING:
+               if (da->flags.length && (len > da->flags.length)) len = da->flags.length;
                data = vp->vp_ptr;
                break;
 
@@ -687,9 +683,9 @@ static ssize_t encode_value(uint8_t *out, size_t outlen,
        case FR_TYPE_IPV6_PREFIX:
                buffer[0] = 0;
                buffer[1] = vp->vp_ip.prefix;
-               len = vp->vp_ip.prefix >> 3;            /* Convert bits to whole bytes */
-               memcpy(buffer, vp->vp_ipv6addr, len);   /* Only copy the minimum number of address bytes required */
-               len += 2;                               /* Reserved and prefix bytes */
+               len = vp->vp_ip.prefix >> 3;                    /* Convert bits to whole bytes */
+               memcpy(buffer + 2, vp->vp_ipv6addr, len);       /* Only copy the minimum number of address bytes required */
+               len += 2;                                       /* Reserved and prefix bytes */
                data = buffer;
                break;
 
@@ -699,7 +695,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen,
        case FR_TYPE_IPV4_PREFIX:
                buffer[0] = 0;
                buffer[1] = vp->vp_ip.prefix;
-               memcpy(buffer, &vp->vp_ipv4addr, sizeof(vp->vp_ipv4addr));
+               memcpy(buffer + 2, &vp->vp_ipv4addr, sizeof(vp->vp_ipv4addr));
                data = buffer;
                break;
 
@@ -758,7 +754,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen,
        }
 
        /*
-        *      Bound the data to the calling size
+        *      Bind the data to the calling size
         */
        if (len > (ssize_t)outlen) len = outlen;
 
@@ -891,7 +887,7 @@ static ssize_t attr_shift(uint8_t const *start, uint8_t const *end,
  */
 static int encode_extended_hdr(uint8_t *out, size_t outlen,
                               fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                              vp_cursor_t *cursor, void *encoder_ctx)
+                              fr_cursor_t *cursor, void *encoder_ctx)
 {
        int                     len;
        fr_type_t               attr_type;
@@ -899,7 +895,7 @@ static int encode_extended_hdr(uint8_t *out, size_t outlen,
        fr_type_t               vsa_type;
 #endif
        uint8_t                 *start = out;
-       VALUE_PAIR const        *vp = fr_pair_cursor_current(cursor);
+       VALUE_PAIR const        *vp = fr_cursor_current(cursor);
 
        VP_VERIFY(vp);
        FR_PROTO_STACK_PRINT(tlv_stack, depth);
@@ -1029,12 +1025,12 @@ static int encode_extended_hdr(uint8_t *out, size_t outlen,
  */
 static ssize_t encode_concat(uint8_t *out, size_t outlen,
                             fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                            vp_cursor_t *cursor, UNUSED void *encoder_ctx)
+                            fr_cursor_t *cursor, UNUSED void *encoder_ctx)
 {
        uint8_t                 *ptr = out;
        uint8_t                 const *p;
        size_t                  len, left;
-       VALUE_PAIR const        *vp = fr_pair_cursor_current(cursor);
+       VALUE_PAIR const        *vp = fr_cursor_current(cursor);
 
        FR_PROTO_STACK_PRINT(tlv_stack, depth);
 
@@ -1089,7 +1085,7 @@ static ssize_t encode_concat(uint8_t *out, size_t outlen,
  */
 static ssize_t encode_rfc_hdr_internal(uint8_t *out, size_t outlen,
                                       fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                                      vp_cursor_t *cursor, void *encoder_ctx)
+                                      fr_cursor_t *cursor, void *encoder_ctx)
 {
        ssize_t len;
 
@@ -1140,7 +1136,7 @@ static ssize_t encode_rfc_hdr_internal(uint8_t *out, size_t outlen,
  */
 static ssize_t encode_vendor_attr_hdr(uint8_t *out, size_t outlen,
                                      fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                                     vp_cursor_t *cursor, void *encoder_ctx)
+                                     fr_cursor_t *cursor, void *encoder_ctx)
 {
        ssize_t                 len;
        size_t                  hdr_len;
@@ -1273,12 +1269,12 @@ static ssize_t encode_vendor_attr_hdr(uint8_t *out, size_t outlen,
  */
 static int encode_wimax_hdr(uint8_t *out, size_t outlen,
                            fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                           vp_cursor_t *cursor, void *encoder_ctx)
+                           fr_cursor_t *cursor, void *encoder_ctx)
 {
        int                     len;
        uint32_t                lvalue;
        uint8_t                 *start = out;
-       VALUE_PAIR const        *vp = fr_pair_cursor_current(cursor);
+       VALUE_PAIR const        *vp = fr_cursor_current(cursor);
 
        VP_VERIFY(vp);
        FR_PROTO_STACK_PRINT(tlv_stack, depth);
@@ -1363,7 +1359,7 @@ static int encode_wimax_hdr(uint8_t *out, size_t outlen,
  */
 static int encode_vsa_hdr(uint8_t *out, size_t outlen,
                          fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                         vp_cursor_t *cursor, void *encoder_ctx)
+                         fr_cursor_t *cursor, void *encoder_ctx)
 {
        ssize_t                 len;
        uint32_t                lvalue;
@@ -1380,7 +1376,9 @@ static int encode_vsa_hdr(uint8_t *out, size_t outlen,
        /*
         *      Double-check for WiMAX format.
         */
-       if (da->vendor == VENDORPEC_WIMAX) return encode_wimax_hdr(out, outlen, tlv_stack, depth + 1, cursor, encoder_ctx);
+       if (da->vendor == VENDORPEC_WIMAX) {
+               return encode_wimax_hdr(out, outlen, tlv_stack, depth + 1, cursor, encoder_ctx);
+       }
 
        /*
         *      Not enough freespace for: attr, len, vendor-id
@@ -1431,9 +1429,9 @@ static int encode_vsa_hdr(uint8_t *out, size_t outlen,
  *
  */
 static int encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **tlv_stack, unsigned int depth,
-                         vp_cursor_t *cursor, void *encoder_ctx)
+                         fr_cursor_t *cursor, void *encoder_ctx)
 {
-       VALUE_PAIR const *vp = fr_pair_cursor_current(cursor);
+       VALUE_PAIR const *vp = fr_cursor_current(cursor);
 
        /*
         *      Sanity checks
@@ -1510,7 +1508,7 @@ static int encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **tl
  *     - 0 Nothing to encode (or attribute skipped).
  *     - <0 an error occurred.
  */
-ssize_t fr_radius_encode_pair(uint8_t *out, size_t outlen, vp_cursor_t *cursor, void *encoder_ctx)
+ssize_t fr_radius_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor, void *encoder_ctx)
 {
        VALUE_PAIR const *vp;
        int ret;
@@ -1631,7 +1629,7 @@ ssize_t fr_radius_encode_pair(uint8_t *out, size_t outlen, vp_cursor_t *cursor,
        /*
         *      We couldn't do it, so we didn't do anything.
         */
-       if (fr_pair_cursor_current(cursor) == vp) {
+       if (fr_cursor_current(cursor) == vp) {
                fr_strerror_printf("%s: Nested attribute structure too large to encode", __FUNCTION__);
                return -1;
        }
index 1235b38b9fca2c13ee2ab3ee780307820b395c17..9e87d97a597da5b01db8d0bf75085c34a867d1fb 100644 (file)
@@ -114,7 +114,7 @@ int fr_radius_packet_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original,
        uint8_t                 *ptr;
        radius_packet_t         *hdr;
        VALUE_PAIR              *head = NULL;
-       vp_cursor_t             cursor, out;
+       fr_cursor_t             cursor, out;
        fr_radius_ctx_t         packet_ctx;
 
        packet_ctx.secret = secret;
@@ -166,7 +166,7 @@ int fr_radius_packet_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original,
        packet_length = packet->data_len - RADIUS_HDR_LEN;
        num_attributes = 0;
 
-       fr_pair_cursor_init(&cursor, &head);
+       fr_cursor_init(&cursor, &head);
 
        /*
         *      Loop over the attributes, decoding them into VPs.
@@ -191,7 +191,7 @@ int fr_radius_packet_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original,
                /*
                 *      Count the ones which were just added
                 */
-               while (fr_pair_cursor_next(&cursor)) num_attributes++;
+               while (fr_cursor_next(&cursor)) num_attributes++;
 
                /*
                 *      VSA's may not have been counted properly in
@@ -216,9 +216,10 @@ int fr_radius_packet_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original,
                packet_length -= my_len;
        }
 
-       fr_pair_cursor_init(&out, &packet->vps);
-       fr_pair_cursor_last(&out);              /* Move insertion point to the end of the list */
-       fr_pair_cursor_merge(&out, head);
+       fr_cursor_init(&out, &packet->vps);
+       fr_cursor_tail(&out);           /* Move insertion point to the end of the list */
+       fr_cursor_head(&cursor);
+       fr_cursor_merge(&out, &cursor);
 
        /*
         *      Merge information from the outside world into our
index af6e8c004a324384c66a2eacea4c8348f1edd352..8b2314ee033ed27eed63212aee74ee5d51557646 100644 (file)
@@ -144,7 +144,7 @@ int         fr_radius_encode_tunnel_password(char *encpw, size_t *len, char const *secr
 
 int            fr_radius_encode_chap_password(uint8_t *output, RADIUS_PACKET *packet, int id, VALUE_PAIR *password);
 
-ssize_t                fr_radius_encode_pair(uint8_t *out, size_t outlen, vp_cursor_t *cursor, void *encoder_ctx);
+ssize_t                fr_radius_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor, void *encoder_ctx);
 
 /*
  *     protocols/radius/decode.c
@@ -157,15 +157,15 @@ ssize_t           fr_radius_decode_password(char *encpw, size_t len, char const *secret,
 ssize_t                fr_radius_decode_tunnel_password(uint8_t *encpw, size_t *len, char const *secret,
                                                 uint8_t const *vector, bool tunnel_password_zeros);
 
-ssize_t                fr_radius_decode_pair_value(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent,
+ssize_t                fr_radius_decode_pair_value(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_attr_t const *parent,
                                            uint8_t const *data, size_t const attr_len, size_t const packet_len,
                                            void *decoder_ctx);
 
-ssize_t                fr_radius_decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent,
+ssize_t                fr_radius_decode_tlv(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_attr_t const *parent,
                                     uint8_t const *data, size_t data_len,
                                     void *decoder_ctx);
 
-ssize_t                fr_radius_decode_pair(TALLOC_CTX *ctx, vp_cursor_t *cursor, uint8_t const *data, size_t data_len,
+ssize_t                fr_radius_decode_pair(TALLOC_CTX *ctx, fr_cursor_t *cursor, uint8_t const *data, size_t data_len,
                                      void *decoder_ctx);
 
 #endif /* _FR_RADIUS_RADIUS_H */