*/
#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, ...)
{
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.
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.
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).
* 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;
}
/*
* 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);
len -= left;
}
- vp = next_encodable(cursor);
+ vp = fr_cursor_next(cursor);
/*
* @fixme: attributes with 'concat' MUST of type
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];
}
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];
}
if (!cursor || !out || (outlen <= 2)) return -1;
- vp = first_encodable(cursor);
+ vp = fr_cursor_head(cursor);
if (!vp) return 0;
VP_VERIFY(vp);
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;
}
}