* and allows the full range of entry indexes which would not be possible if we represented
* table index numbers as TLV attributes.
*
- * @param ctx to allocate new pairs in.
- * @param conf radsnmp config.
- * @param cursor to add pairs to.
- * @param oid string to evaluate.
- * @param type SNMP value type.
- * @param value to assign to OID attribute (SET operations only).
+ * @param[in] ctx to allocate new pairs in.
+ * @param[in] conf radsnmp config.
+ * @param[in] cursor to add pairs to.
+ * @param[in] oid string to evaluate.
+ * @param[in] type SNMP value type.
+ * @param[in] value to assign to OID attribute (SET operations only).
* @return
* - >0 on success (how much of the OID string we parsed).
* - <=0 on failure (where format error occurred).
*/
-static ssize_t radsnmp_pair_from_oid(TALLOC_CTX *ctx, radsnmp_conf_t *conf, vp_cursor_t *cursor,
+static ssize_t radsnmp_pair_from_oid(TALLOC_CTX *ctx, radsnmp_conf_t *conf, fr_cursor_t *cursor,
char const *oid, int type, char const *value)
{
ssize_t slen;
if (!oid) return 0;
- fr_pair_cursor_end(cursor);
+ fr_cursor_tail(cursor);
/*
* Trim first.
MEM(vp = fr_pair_afrom_da(ctx, index_attr));
vp->vp_uint32 = attr;
- fr_pair_cursor_append(cursor, vp);
+ fr_cursor_append(cursor, vp);
}
/*
*/
if (slen <= 0) {
error:
- fr_pair_cursor_free(cursor);
+ fr_cursor_free_list(cursor);
return slen;
}
break;
}
- fr_pair_cursor_append(cursor, vp);
+ fr_cursor_append(cursor, vp);
return slen;
}
}
vp->vp_uint32 = type;
- fr_pair_cursor_append(cursor, vp);
+ fr_cursor_append(cursor, vp);
return slen;
}
fr_dict_attr_t const *root, fr_dict_attr_t const *type,
VALUE_PAIR *head)
{
- vp_cursor_t cursor;
+ fr_cursor_t cursor;
VALUE_PAIR *vp, *type_vp;
fr_dict_attr_t const *parent = root;
unsigned int written = 0;
* attribute grouping to coalesce all related index
* attributes under a single request OID.
*/
- for (vp = fr_pair_cursor_init(&cursor, &head);
+ for (vp = fr_cursor_init(&cursor, &head);
vp;
- vp = fr_pair_cursor_next(&cursor)) {
+ vp = fr_cursor_next(&cursor)) {
fr_dict_attr_t const *common;
/*
* We only care about TLV attributes beneath our root
/*
* Next attribute should be the type
*/
- type_vp = fr_pair_cursor_next(&cursor);
+ type_vp = fr_cursor_next(&cursor);
if (!type_vp || (type_vp->da != type)) {
fr_strerror_printf("No %s found in response, or occurred out of order", type->name);
return -1;
char *line;
ssize_t slen;
- vp_cursor_t cursor;
+ fr_cursor_t cursor;
VALUE_PAIR *vp;
RADIUS_PACKET *request;
ERROR("Failed allocating request");
return EXIT_FAILURE;
}
- fr_pair_cursor_init(&cursor, &request->vps);
+ fr_cursor_init(&cursor, &request->vps);
NEXT_LINE(line, buffer);
return EXIT_FAILURE;
}
vp->vp_uint32 = (unsigned int)command; /* Commands must match dictionary */
- fr_pair_cursor_append(&cursor, vp);
+ fr_cursor_append(&cursor, vp);
/*
* Add message authenticator or the stats
*/
MEM(vp = fr_pair_afrom_da(request, attr_message_authenticator));
fr_pair_value_memcpy(vp, (uint8_t const *)"\0", 1);
- fr_pair_cursor_append(&cursor, vp);
+ fr_cursor_append(&cursor, vp);
/*
* Send the packet
SNMP_MAP_TERMINATOR
};
-static ssize_t snmp_process(vp_cursor_t *out, REQUEST *request,
+static ssize_t snmp_process(fr_cursor_t *out, REQUEST *request,
fr_dict_attr_t const *tlv_stack[], unsigned int depth,
- vp_cursor_t *cursor,
+ fr_cursor_t *cursor,
fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op);
/** Perform a binary search to find a map matching a da
tlv_stack[i] = NULL;
}
-static ssize_t snmp_process_index(vp_cursor_t *out, REQUEST *request,
+static ssize_t snmp_process_index(fr_cursor_t *out, REQUEST *request,
fr_dict_attr_t const *tlv_stack[], unsigned int depth,
- vp_cursor_t cursor,
+ fr_cursor_t cursor,
fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op,
uint32_t index_num)
{
return ret; /* no more entries at this level, findNext at lower level */
}
- ret = snmp_process(out, request, tlv_stack, depth + 1, &cursor, map->child,
- this_snmp_ctx, snmp_op);
+ ret = snmp_process(out, request,
+ tlv_stack, depth + 1,
+ &cursor,
+ map->child, this_snmp_ctx, snmp_op);
TALLOC_FREE(tmp_ctx);
if (ret < 0) return ret; /* error */
if (!vp) return 0;
vp->vp_uint32 = i;
- fr_pair_cursor_prepend(out, vp);
+ fr_cursor_prepend(out, vp);
return 0; /* done */
}
return -(depth);
}
-static ssize_t snmp_process_index_attr(vp_cursor_t *out, REQUEST *request,
+static ssize_t snmp_process_index_attr(fr_cursor_t *out, REQUEST *request,
fr_dict_attr_t const *tlv_stack[], unsigned int depth,
- vp_cursor_t *cursor,
+ fr_cursor_t *cursor,
fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op)
{
VALUE_PAIR *next;
/*
* Get the index from the index attribute's value.
*/
- vp = fr_pair_cursor_current(cursor);
+ vp = fr_cursor_current(cursor);
index_num = vp->vp_uint32;
/*
* Advance the cursor to the next index attribute
* if it is an index attribute...
*/
- next = fr_pair_cursor_next_peek(cursor);
+ next = fr_cursor_next_peek(cursor);
if (next && fr_dict_parent_common(vp->da, next->da, true)) {
fr_proto_tlv_stack_build(tlv_stack, next->da);
- fr_pair_cursor_next_by_ancestor(cursor, vp->da, TAG_ANY);
+
+ while ((next = fr_cursor_next(cursor))) if (fr_dict_parent_common(vp->da, next->da, true)) break;
}
- return snmp_process_index(out, request, tlv_stack, depth, *cursor, &map[1], snmp_ctx, snmp_op, index_num);
+ return snmp_process_index(out, request,
+ tlv_stack, depth,
+ *cursor,
+ &map[1], snmp_ctx, snmp_op,
+ index_num);
}
-static ssize_t snmp_process_tlv(vp_cursor_t *out, REQUEST *request,
+static ssize_t snmp_process_tlv(fr_cursor_t *out, REQUEST *request,
fr_dict_attr_t const *tlv_stack[], unsigned int depth,
- vp_cursor_t *cursor,
+ fr_cursor_t *cursor,
fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op)
{
fr_snmp_map_t const *map_p;
* fake index attributes
*/
if (map_p->index) {
- return snmp_process_index(out, request, tlv_stack, depth, *cursor,
- map_p, snmp_ctx, snmp_op, tlv_stack[depth]->attr);
+ return snmp_process_index(out, request,
+ tlv_stack, depth,
+ *cursor,
+ map_p, snmp_ctx, snmp_op,
+ tlv_stack[depth]->attr);
}
for (;;) {
- ret = snmp_process(out, request, tlv_stack, depth + 1, cursor, map_p->child,
- snmp_ctx, snmp_op);
+ ret = snmp_process(out, request,
+ tlv_stack, depth + 1,
+ cursor,
+ map_p->child, snmp_ctx, snmp_op);
if (ret < 0) return ret; /* error */
if (ret > 0) { /* findNext */
if (snmp_op != FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT) goto invalid;
}
}
-static ssize_t snmp_process_leaf(vp_cursor_t *out, REQUEST *request,
+static ssize_t snmp_process_leaf(fr_cursor_t *out, REQUEST *request,
fr_dict_attr_t const *tlv_stack[], unsigned int depth,
- vp_cursor_t *cursor,
+ fr_cursor_t *cursor,
fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op)
{
VALUE_PAIR *vp;
FR_PROTO_STACK_PRINT(tlv_stack, depth);
- vp = fr_pair_cursor_current(cursor);
+ vp = fr_cursor_current(cursor);
/*
* Return element in map that matches the da at this
* to a non-leaf map.
*/
if (map_p->type == FR_FREERADIUS_SNMP_TYPE_OBJECT) {
- return snmp_process(out, request, tlv_stack, depth + 1,
- cursor, map_p->child, snmp_ctx, snmp_op);
+ return snmp_process(out, request,
+ tlv_stack, depth + 1,
+ cursor,
+ map_p->child, snmp_ctx, snmp_op);
}
}
/* FALL-THROUGH */
vp = fr_pair_afrom_da(request->reply, map_p->da);
if (!vp) return 0;
fr_value_box_steal(vp, &vp->data, &data);
- fr_pair_cursor_append(out, vp);
+ fr_cursor_append(out, vp);
vp = fr_pair_afrom_da(request->reply, fr_snmp_type);
if (!vp) return 0;
vp->vp_uint32 = map_p->type;
- fr_pair_cursor_append(out, vp);
+ fr_cursor_append(out, vp);
}
return 0;
vp = fr_pair_afrom_da(request->reply, fr_snmp_failure);
if (!vp) return 0;
vp->vp_uint32 = FR_FREERADIUS_SNMP_FAILURE_VALUE_NOT_WRITABLE;
- fr_pair_cursor_append(out, vp);
+ fr_cursor_append(out, vp);
return 0;
}
- vp = fr_pair_cursor_current(cursor);
+ vp = fr_cursor_current(cursor);
ret = map_p->set(map_p, snmp_ctx, &vp->data);
if (ret < 0) switch (-(ret)) {
case FR_FREERADIUS_SNMP_FAILURE_VALUE_NOT_WRITABLE:
if (!vp) break;
vp->vp_uint32 = -(ret);
- fr_pair_cursor_append(out, vp);
+ fr_cursor_append(out, vp);
break;
default:
/** Traverse a tree of SNMP maps
*
- * @param[out] out Where to write response attributes.
- * @param[in] request The current request.
- * @param[in,out] tlv_stack we're traversing.
- * @param[in] depth we're currently at in the tlv_stack.
- * @param[in] cursor representing the current attribute we're processing.
- * @param[in] map matching the current depth in the tlv_stack.
- * @param[in] snmp_ctx allocated by the previous index traversal function.
- * @param[in] snmp_op we're performing.
+ * @param[out] out Where to write response attributes.
+ * @param[in] request The current request.
+ * @param[in,out] tlv_stack we're traversing.
+ * @param[in] depth we're currently at in the tlv_stack.
+ * @param[in] cursor representing the current attribute we're processing.
+ * @param[in] map matching the current depth in the tlv_stack.
+ * @param[in] snmp_ctx allocated by the previous index traversal function.
+ * @param[in] snmp_op we're performing.
* @return
* - 0 on success.
* - 1 to signal caller that it should find the next OID at this level
* and recurse again.
* - <0 the depth at which an error occurred, as a negative integer.
*/
-static ssize_t snmp_process(vp_cursor_t *out, REQUEST *request,
+static ssize_t snmp_process(fr_cursor_t *out, REQUEST *request,
fr_dict_attr_t const *tlv_stack[], unsigned int depth,
- vp_cursor_t *cursor,
+ fr_cursor_t *cursor,
fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op)
{
rad_assert(map);
* It's an index attribute, use the value of
* the index attribute to traverse the index.
*/
- if (tlv_stack[depth]->attr == 0) return snmp_process_index_attr(out, request, tlv_stack, depth, cursor,
+ if (tlv_stack[depth]->attr == 0) return snmp_process_index_attr(out, request,
+ tlv_stack, depth,
+ cursor,
map, snmp_ctx, snmp_op);
/*
* matching the next deepest DA in the
* tlv_stack.
*/
- if (tlv_stack[depth]->type == FR_TYPE_TLV) return snmp_process_tlv(out, request, tlv_stack, depth, cursor,
+ if (tlv_stack[depth]->type == FR_TYPE_TLV) return snmp_process_tlv(out, request,
+ tlv_stack, depth,
+ cursor,
map, snmp_ctx, snmp_op);
/*
* Must be a leaf, call the appropriate get/set function
* and create attributes for the response.
*/
- return snmp_process_leaf(out, request, tlv_stack, depth, cursor, map, snmp_ctx, snmp_op);
+ return snmp_process_leaf(out, request,
+ tlv_stack, depth,
+ cursor,
+ map, snmp_ctx, snmp_op);
}
int fr_snmp_process(REQUEST *request)
{
- vp_cursor_t request_cursor, op_cursor, out_cursor, reply_cursor;
+ fr_cursor_t request_cursor, op_cursor, out_cursor, reply_cursor;
VALUE_PAIR *head = NULL, *vp;
char oid_str[FR_DICT_MAX_TLV_STACK * 4]; /* .<num>{1,3} */
VALUE_PAIR *op;
- fr_pair_cursor_init(&request_cursor, &request->packet->vps);
- fr_pair_cursor_init(&op_cursor, &request->packet->vps);
- fr_pair_cursor_init(&reply_cursor, &request->reply->vps);
- fr_pair_cursor_init(&out_cursor, &head);
+ fr_cursor_init(&request_cursor, &request->packet->vps);
+ fr_cursor_talloc_iter_init(&op_cursor, &request->packet->vps,
+ fr_pair_iter_next_by_da, fr_snmp_op_attr, VALUE_PAIR);
+ fr_cursor_init(&reply_cursor, &request->reply->vps);
+ fr_cursor_init(&out_cursor, &head);
RDEBUG2("Processing SNMP stats request");
* not allowed in the RADIUS protocol, so we
* encode the TLV as an octet type attribute
*/
- for (vp = fr_pair_cursor_first(&request_cursor);
+ for (vp = fr_cursor_head(&request_cursor);
vp;
- vp = fr_pair_cursor_next(&request_cursor)) {
+ vp = fr_cursor_next(&request_cursor)) {
fr_dict_attr_t const *da;
if (!vp->da->flags.is_unknown) continue;
}
vp->da = da;
}
- fr_pair_cursor_first(&request_cursor);
- while ((vp = fr_pair_cursor_next_by_ancestor(&request_cursor, fr_snmp_root, TAG_ANY))) {
+ for (vp = fr_cursor_talloc_iter_init(&request_cursor, &request->packet->vps,
+ fr_pair_iter_next_by_ancestor, fr_snmp_root, VALUE_PAIR);
+ vp;
+ vp = fr_cursor_next(&request_cursor)) {
fr_proto_tlv_stack_build(tlv_stack, vp->da);
/*
for (depth = 0; tlv_stack[depth]; depth++) if (fr_snmp_root == tlv_stack[depth]) break;
/*
- * Any attribute returned by fr_pair_cursor_next_by_ancestor
+ * Any attribute returned by fr_cursor_next_by_ancestor
* should have the SNMP root attribute as an ancestor.
*/
rad_assert(tlv_stack[depth]);
/*
* Operator attribute acts as a request delimiter
*/
- op = fr_pair_cursor_next_by_da(&op_cursor, fr_snmp_op_attr, TAG_ANY);
+ op = fr_cursor_current(&op_cursor);
if (!op) {
ERROR("Missing operation (%s)", fr_snmp_op_attr->name);
return -1;
}
+ fr_cursor_next(&op_cursor);
switch (op->vp_uint32) {
case FR_FREERADIUS_SNMP_OPERATION_VALUE_PING:
/*
* Returns depth (as negative integer) at which the error occurred
*/
- ret = snmp_process(&out_cursor, request, tlv_stack, depth,
- &request_cursor, snmp_iso, NULL, op->vp_uint32);
+ ret = snmp_process(&out_cursor, request,
+ tlv_stack, depth,
+ &request_cursor,
+ snmp_iso, NULL, op->vp_uint32);
if (ret < 0) {
fr_pair_list_free(&head);
}
}
- fr_pair_cursor_merge(&reply_cursor, head);
+ fr_cursor_head(&out_cursor);
+ fr_cursor_merge(&reply_cursor, &out_cursor);
return 0;
}