]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
radius: Move to using an iterator for skipping non-encodable attributes
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 27 Mar 2020 14:29:18 +0000 (08:29 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 27 Mar 2020 14:29:18 +0000 (08:29 -0600)
src/lib/util/proto.c
src/lib/util/proto.h
src/protocols/radius/base.c
src/protocols/radius/encode.c

index 18e2aeb7a57247dc5ca19e23afb394cd7fea7e0f..580fc69b2beb48a7875699fc06702de1ebd4bff6 100644 (file)
@@ -22,6 +22,7 @@
  */
 #include <freeradius-devel/util/print.h>
 #include <freeradius-devel/util/proto.h>
+#include <freeradius-devel/util/pair.h>
 
 void fr_proto_print(char const *file, int line, char const *fmt, ...)
 {
@@ -71,7 +72,36 @@ void fr_proto_da_stack_print(char const *file, int line, char const *func, fr_da
        fr_log(&default_log, L_DBG, file, line, "stk:");
 }
 
-/** Build a complete TLV stack from the da back to the root
+/** Implements the default iterator to encode pairs belonging to a specific dictionary that are not internal
+ *
+ * @param[in,out] prev The VALUE_PAIR before curr. Will be updated to point to the
+ *                     pair before the one returned, or the last pair in the list
+ *                     if no matching pairs found.
+ * @param[in] to_eval  The VALUE_PAIR after cursor->current.  Will be checked to
+ *                     see if it matches the specified fr_dict_attr_t.
+ * @param[in] uctx     The fr_dict_attr_t to search for.
+ * @return
+ *     - Next matching VALUE_PAIR.
+ *     - NULL if not more matching VALUE_PAIRs could be found.
+ */
+void *fr_proto_next_encodable(void **prev, void *to_eval, void *uctx)
+{
+       VALUE_PAIR      *c, *p;
+       fr_dict_t       *dict = talloc_get_type_abort(uctx, fr_dict_t);
+
+       if (!to_eval) return NULL;
+
+       for (p = *prev, c = to_eval; c; p = c, c = c->next) {
+               VP_VERIFY(c);
+               if ((c->da->dict == dict) && (!c->da->flags.internal)) break;
+       }
+
+       *prev = p;
+
+       return c;
+}
+
+/** Build a complete DA stack from the da back to the root
  *
  * @param[out] stack   to populate.
  * @param[in] da       to build the stack for.
@@ -94,7 +124,7 @@ void fr_proto_da_stack_build(fr_da_stack_t *stack, fr_dict_attr_t const *da)
        stack->da[stack->depth] = NULL;
 }
 
-/** Complete the tlv stack for a child attribute
+/** Complete the DA stack for a child attribute
  *
  * @param[out] stack           to populate.
  * @param[in] parent           to populate from.
index e08bea8d1acc46fb938558c0c309b9acafaaf4c7..7e32732eab656b4810bb9cb0d81a6a21f610bb1e 100644 (file)
@@ -57,6 +57,8 @@ void fr_proto_print(char const *file, int line, char const *fmt, ...) CC_HINT(fo
 
 void fr_proto_print_hex_data(char const *file, int line, uint8_t const *data, size_t data_len, char const *fmt, ...);
 
+void *fr_proto_next_encodable(void **prev, void *to_eval, void *uctx);
+
 void fr_proto_da_stack_print(char const *file, int line, char const *func, fr_da_stack_t *da_stack, unsigned int depth);
 
 void fr_proto_da_stack_build(fr_da_stack_t *stack, fr_dict_attr_t const *da);
index 5b2ecdae35493d5362b64a85d8ee7e1fcc2034f1..d2130cf41b6e99e6818e28d2fd4da6d229252ee4 100644 (file)
@@ -969,7 +969,7 @@ 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_cursor_init(&cursor, &vps);
+       fr_cursor_talloc_iter_init(&cursor, &vps, fr_proto_next_encodable, dict_radius, VALUE_PAIR);
        while ((vp = fr_cursor_current(&cursor))) {
                size_t          last_len, room;
                char const      *last_name = NULL;
index 07e50d3ca75fa9fdc4add7fe077dd32a97b13570..83f91cef382dcfd112f6992eb937df9e9df1bb65 100644 (file)
@@ -42,42 +42,6 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen,
                              fr_da_stack_t *da_stack, unsigned int depth,
                              fr_cursor_t *cursor, void *encoder_ctx);
 
-static inline bool is_encodable(VALUE_PAIR const *vp)
-{
-       if (!vp) return false;
-       if (vp->da->flags.internal) return false;
-
-       return true;
-}
-
-/** Find the next attribute to encode
- *
- * @param cursor to iterate over.
- * @return encodable VALUE_PAIR, or NULL if none available.
- */
-static inline VALUE_PAIR *next_encodable(fr_cursor_t *cursor)
-{
-       VALUE_PAIR *vp;
-
-       do { vp = fr_cursor_next(cursor); } while (vp && !is_encodable(vp));
-       return fr_cursor_current(cursor);
-}
-
-/** Determine if the current attribute is encodable, or find the first one that is
- *
- * @param cursor to iterate over.
- * @return encodable VALUE_PAIR, or NULL if none available.
- */
-static inline VALUE_PAIR *first_encodable(fr_cursor_t *cursor)
-{
-       VALUE_PAIR *vp;
-
-       vp = fr_cursor_current(cursor);
-       if (is_encodable(vp)) return vp;
-
-       return next_encodable(cursor);
-}
-
 /** Encode a CHAP password
  *
  * @param[out] out             An output buffer of 17 bytes (id + digest).
@@ -556,7 +520,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen,
         *      be written.
         */
        if (!data || (len == 0)) {
-               vp = next_encodable(cursor);
+               vp = fr_cursor_next(cursor);
                fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
                return 0;
        }
@@ -633,7 +597,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen,
        /*
         *      Rebuilds the TLV stack for encoding the next attribute
         */
-       vp = next_encodable(cursor);
+       vp = fr_cursor_next(cursor);
        fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
 
        return len + (ptr - out);
@@ -861,7 +825,7 @@ static ssize_t encode_concat(uint8_t *out, size_t outlen,
                len -= left;
        }
 
-       vp = next_encodable(cursor);
+       vp = fr_cursor_next(cursor);
 
        /*
         *      @fixme: attributes with 'concat' MUST of type
@@ -1208,7 +1172,7 @@ static int encode_rfc_hdr(uint8_t *out, size_t outlen, fr_da_stack_t *da_stack,
 
                FR_PROTO_HEX_DUMP(out, 2, "header rfc");
 
-               vp = next_encodable(cursor);
+               vp = fr_cursor_next(cursor);
                fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
                return out[1];
        }
@@ -1226,7 +1190,7 @@ static int encode_rfc_hdr(uint8_t *out, size_t outlen, fr_da_stack_t *da_stack,
                FR_PROTO_HEX_DUMP(out + 2, RADIUS_MESSAGE_AUTHENTICATOR_LENGTH, "message-authenticator");
                FR_PROTO_HEX_DUMP(out, 2, "header rfc");
 
-               vp = next_encodable(cursor);
+               vp = fr_cursor_next(cursor);
                fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
                return out[1];
        }
@@ -1260,7 +1224,7 @@ ssize_t fr_radius_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor,
 
        if (!cursor || !out || (outlen <= 2)) return -1;
 
-       vp = first_encodable(cursor);
+       vp = fr_cursor_head(cursor);
        if (!vp) return 0;
 
        VP_VERIFY(vp);
@@ -1280,7 +1244,7 @@ ssize_t fr_radius_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor,
                if (!fr_dict_attr_is_top_level(vp->da) ||
                    ((vp->da->attr != FR_CHARGEABLE_USER_IDENTITY) &&
                     (vp->da->attr != FR_MESSAGE_AUTHENTICATOR))) {
-                       next_encodable(cursor);
+                       fr_cursor_next(cursor);
                        return 0;
                }
        }