* It might be too big for putting into an
* EAP packet.
*/
- vp = fr_pair_find_by_child_num(to_encode, fr_dict_root(dict_eap_aka_sim), FR_SUBTYPE);
+ vp = fr_pair_find_by_child_num(to_encode, fr_dict_root(dict_eap_aka_sim), FR_SUBTYPE, 0);
if (!vp) {
REDEBUG("Missing subtype attribute");
return PAIR_ENCODE_FATAL_ERROR;
/*
* Will we need to generate a HMAC?
*/
- if (fr_pair_find_by_child_num(to_encode, fr_dict_root(dict_eap_aka_sim), FR_MAC)) do_hmac = true;
+ if (fr_pair_find_by_child_num(to_encode, fr_dict_root(dict_eap_aka_sim), FR_MAC, 0)) do_hmac = true;
/*
* Fast path, we just need to encode a subtype
/** Find a pair which has the specified ancestor
*
* @param[in] list to search in.
+ * @param[in] prev where to start the search from.
* @param[in] ancestor to look for in the list.
* @return
* - first matching fr_pair_t.
*
* @hidecallergraph
*/
-fr_pair_t *fr_pair_find_by_ancestor(fr_pair_list_t const *list, fr_dict_attr_t const *ancestor)
+fr_pair_t *fr_pair_find_by_ancestor(fr_pair_list_t const *list,
+ fr_pair_t const *prev, fr_dict_attr_t const *ancestor)
{
- fr_pair_t *vp = NULL;
+ fr_pair_t *vp = UNCONST(fr_pair_t *, prev);
while ((vp = fr_pair_list_next(list, vp))) {
if (!fr_dict_attr_common_parent(ancestor, vp->da, true)) continue;
* @param[in] list in which to search.
* @param[in] parent attribute in which to lookup child.
* @param[in] attr id of child.
+ * @param[in] n Instance of the attribute to return.
* @return
* - first matching value pair.
* - NULL if no pair found.
*/
-fr_pair_t *fr_pair_find_by_child_num(fr_pair_list_t *list, fr_dict_attr_t const *parent, unsigned int attr)
+fr_pair_t *fr_pair_find_by_child_num(fr_pair_list_t *list,
+ fr_dict_attr_t const *parent, unsigned int attr, unsigned int n)
{
fr_dict_attr_t const *da;
- fr_pair_t *vp;
/* List head may be NULL if it contains no VPs */
if (fr_dlist_empty(&list->order)) return NULL;
da = fr_dict_attr_child_by_num(parent, attr);
if (!da) return NULL;
- for (vp = fr_pair_list_head(list); vp != NULL; vp = fr_pair_list_next(list, vp)) if (da == vp->da) return vp;
-
- return NULL;
+ return fr_pair_find_by_da(list, da, n);
}
/** Return a pointer to the pair list
fr_pair_t *fr_pair_find_by_da(fr_pair_list_t const *list,
fr_dict_attr_t const *da, unsigned int n) CC_HINT(nonnull);
-fr_pair_t *fr_pair_find_by_ancestor(fr_pair_list_t const *list,
- fr_dict_attr_t const *ancestor) CC_HINT(nonnull);
+fr_pair_t *fr_pair_find_by_ancestor(fr_pair_list_t const *list, fr_pair_t const *prev,
+ fr_dict_attr_t const *ancestor) CC_HINT(nonnull(1,3));
fr_pair_t *fr_pair_find_by_child_num(fr_pair_list_t *list,
- fr_dict_attr_t const *parent, unsigned int attr) CC_HINT(nonnull);
+ fr_dict_attr_t const *parent, unsigned int attr,
+ unsigned int n) CC_HINT(nonnull);
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *vp) CC_HINT(nonnull);
fr_pair_t *vp;
TEST_CASE("Search for FR_TEST_ATTR_STRING using fr_pair_find_by_child_num()");
- TEST_CHECK((vp = fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING)) != NULL);
+ TEST_CHECK((vp = fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING, 0)) != NULL);
TEST_CASE("Validating PAIR_VERIFY()");
PAIR_VERIFY(vp);
fr_pair_delete_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING);
TEST_CASE("The fr_dict_attr_test_string shouldn't exist in 'test_pairs'");
- TEST_CHECK(fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING) == NULL);
+ TEST_CHECK(fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING, 0) == NULL);
TEST_CASE("Add fr_dict_attr_test_string back into 'test_pairs'");
TEST_CHECK(fr_pair_prepend_by_da(autofree, NULL, &test_pairs, fr_dict_attr_test_string) == 0);
fr_pair_t *vp;
TEST_CASE("Delete fr_dict_attr_test_string using fr_pair_delete()");
- TEST_CHECK((vp = fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING)) != NULL);
+ TEST_CHECK((vp = fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING, 0)) != NULL);
fr_pair_delete(&test_pairs, vp);
TEST_CASE("The fr_dict_attr_test_string shouldn't exist in 'test_pairs'");
- TEST_CHECK((vp = fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING)) == NULL);
+ TEST_CHECK((vp = fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING, 0)) == NULL);
TEST_CASE("Add fr_dict_attr_test_string back into 'test_pairs'");
TEST_CHECK(fr_pair_prepend_by_da(autofree, NULL, &test_pairs, fr_dict_attr_test_string) == 0);
*/
typedef struct {
fr_pair_t *transaction_id;
- fr_pair_t *client_id;
- fr_pair_t *server_id;
+ fr_pair_list_t client_id;
+ fr_pair_list_t server_id;
} process_dhcpv6_client_fields_t;
/** Records fields from the original relay-request so we have a known good copy
return NULL;
}
- client_id = fr_pair_find_by_ancestor(&request->request_pairs, attr_client_id);
+ client_id = fr_pair_find_by_ancestor(&request->request_pairs, NULL, attr_client_id);
if (!client_id) {
REDEBUG("Missing Client-ID");
return NULL;
}
- server_id = fr_pair_find_by_da(&request->request_pairs, attr_server_id, 0);
+ server_id = fr_pair_find_by_ancestor(&request->request_pairs, NULL, attr_server_id);
if (!server_id && expect_server_id) {
REDEBUG("Missing Server-ID");
return NULL;
MEM(rctx = talloc_zero(unlang_interpret_frame_talloc_ctx(request), process_dhcpv6_client_fields_t));
rctx->transaction_id = fr_pair_copy(rctx, transaction_id);
- rctx->client_id = fr_pair_copy(rctx, client_id);
- if (expect_server_id) rctx->server_id = fr_pair_copy(rctx, server_id);
+
+ /*
+ * These should just become straight copies
+ * when the structure pairs are nested.
+ */
+ if (fr_pair_list_copy_by_ancestor(rctx, &rctx->client_id,
+ &request->request_pairs, attr_client_id, 0) < 0) {
+ REDEBUG("Error copying Client-ID");
+ error:
+ talloc_free(rctx);
+ return NULL;
+ }
+
+ if (expect_server_id) {
+ if (fr_pair_list_copy_by_ancestor(rctx, &rctx->server_id,
+ &request->request_pairs, attr_server_id, 0) < 0) {
+ REDEBUG("Error copying Server-ID");
+ goto error;
+ }
+ }
return rctx;
}
static inline CC_HINT(always_inline)
int restore_field(request_t *request, fr_pair_t **to_restore)
{
- fr_pair_t *vp;
+ fr_pair_t *vp;
+ int ret = 0;
PAIR_VERIFY(*to_restore);
if (vp) {
if (fr_pair_cmp(vp, *to_restore) != 0) {
RWDEBUG("&reply.%pP does not match &request.%pP", vp, *to_restore);
- return 0;
+ free:
+ talloc_free(*to_restore);
+ *to_restore = NULL;
+ return ret;
}
} else if (fr_pair_steal_append(request->reply_ctx, &request->reply_pairs, *to_restore) < 0) {
RPERROR("Failed adding %s", (*to_restore)->da->name);
- return -1;
+ ret = -1;
+ goto free;
}
*to_restore = NULL;
return 0;
}
+static inline CC_HINT(always_inline)
+int restore_field_list(request_t *request, fr_pair_list_t *to_restore)
+{
+ fr_pair_t *vp;
+
+ while ((vp = fr_pair_list_head(to_restore))) {
+ fr_pair_remove(to_restore, vp);
+ if (restore_field(request, &vp) < 0) return -1;
+ }
+
+ return 0;
+}
+
+
/** Add a status code if one doesn't already exist
*
*/
*p_result = RLM_MODULE_FAIL;
return CALL_RESUME(send_generic);
}
- if (unlikely(restore_field(request, &fields->client_id) < 0)) goto fail;
- if (fields->server_id && unlikely(restore_field(request, &fields->server_id) < 0)) goto fail;
+ if (unlikely(restore_field_list(request, &fields->client_id) < 0)) goto fail;
+ if (unlikely(restore_field_list(request, &fields->server_id) < 0)) goto fail;
+
+ dhcpv6_packet_debug(request, request->reply, &request->reply_pairs, false);
return CALL_RESUME(send_generic);
}
if (unlikely(restore_field(request, &fields->link_address) < 0)) goto fail;
if (unlikely(restore_field(request, &fields->peer_address) < 0)) goto fail;
+ dhcpv6_packet_debug(request, request->reply, &request->reply_pairs, false);
+
return CALL_RESUME(send_generic);
}