# Range: 1 - 10
# Attribute lists
#
-ATTRIBUTE Request 1 group
-ATTRIBUTE Reply 2 group
-ATTRIBUTE Session-State 3 group
+ATTRIBUTE Root 1 group
+ATTRIBUTE Request 2 group
+ATTRIBUTE Reply 3 group
ATTRIBUTE Control 4 group
+ATTRIBUTE Session-State 5 group
+
#
# Range: 11 - 19
#include "radclient.h"
-#define pair_update_request(_attr, _da) fr_pair_update_by_da(request->packet, _attr, &request->request_pairs, _da)
+#define pair_update_request(_attr, _da) fr_pair_update_by_da(request, _attr, &request->request_pairs, _da)
+#define request_pairs request_list
+#define reply_pairs reply_list
static int retries = 3;
static fr_time_delta_t timeout = ((fr_time_delta_t) 5) * NSEC;
/*
* Read the request VP's.
*/
- if (fr_pair_list_afrom_file(request->packet, dict_radius,
+ if (fr_pair_list_afrom_file(request, dict_radius,
&request->request_pairs, packets, &packets_done) < 0) {
char const *input;
static request_t *request_from_file(TALLOC_CTX *ctx, FILE *fp, fr_event_list_t *el, RADCLIENT *client)
{
fr_pair_t *vp;
- request_t *request;
+ request_t *request;
fr_cursor_t cursor;
static int number = 0;
/*
* Create and initialize the new request.
*/
- request = request_local_alloc(ctx);
-
+ request = request_local_alloc(ctx, NULL);
/*
* FIXME - Should be less RADIUS centric, but everything
* else assumes RADIUS at the moment so we can fix this later.
/*
* Read packet from fp
*/
- if (fr_pair_list_afrom_file(request->packet, dict_protocol, &request->request_pairs, fp, &filedone) < 0) {
+ if (fr_pair_list_afrom_file(request->request_ctx, dict_protocol, &request->request_pairs, fp, &filedone) < 0) {
fr_perror("%s", main_config->name);
talloc_free(request);
return NULL;
/*
* Create and initialize the new request.
*/
- request = request_alloc(NULL);
+ request = request_alloc(NULL, NULL);
request->log.dst = talloc_zero(request, log_dst_t);
request->log.dst->func = vlog_request;
{
request_t *request;
- request = request_alloc(NULL);
+ request = request_alloc(NULL, NULL);
if (!request) return NULL;
if (!request->packet) request->packet = fr_radius_packet_alloc(request, false);
if (!request->reply) request->reply = fr_radius_packet_alloc(request, false);
memcpy(request->packet, old->packet, sizeof(*request->packet));
- (void) fr_pair_list_copy(request->packet, &request->request_pairs, &old->request_pairs);
+ (void) fr_pair_list_copy(request->request_ctx, &request->request_pairs, &old->request_pairs);
request->packet->timestamp = fr_time();
request->number = old->number++;
}
}
- if (fr_pair_list_afrom_file(request, dict_protocol, &filter_vps, fp, &filedone) < 0) {
+ if (fr_pair_list_afrom_file(request->request_ctx, dict_protocol, &filter_vps, fp, &filedone) < 0) {
fr_perror("Failed reading attributes from %s", filter_file);
EXIT_WITH_FAILURE;
}
RDEBUG3("If this value is required, define attribute \"%s\"", buffer);
continue;
}
- MEM(vp = fr_pair_afrom_da(request->packet, da));
+ MEM(vp = fr_pair_afrom_da(request->request_ctx, da));
fr_pair_value_from_str(vp, q + 1, -1, '\0', true);
fr_cursor_append(&cursor, vp);
(chbind->response == NULL));
/* Set-up the fake request */
- fake = request_alloc_fake(request, NULL);
- MEM(fr_pair_add_by_da(fake->packet, &vp, &fake->request_pairs, attr_freeradius_proxied_to) >= 0);
+ fake = request_alloc(request, &(request_init_args_t){ .parent = request });
+ MEM(fr_pair_add_by_da(fake->request_ctx, &vp, &fake->request_pairs, attr_freeradius_proxied_to) >= 0);
fr_pair_value_from_str(vp, "127.0.0.1", sizeof("127.0.0.1"), '\0', false);
/* Add the username to the fake request */
if (chbind->username) {
- vp = fr_pair_copy(fake->packet, chbind->username);
+ vp = fr_pair_copy(fake->request_ctx, chbind->username);
fr_pair_add(&fake->request_pairs, vp);
}
while (data_len > 0) {
ssize_t attr_len;
- attr_len = fr_radius_decode_pair(fake->packet, &cursor, dict_radius,
+ attr_len = fr_radius_decode_pair(fake->request_ctx, &cursor, dict_radius,
attr_data, data_len, NULL);
if (attr_len <= 0) {
/*
return packet;
}
-fr_pair_t *eap_chbind_packet2vp(fr_radius_packet_t *packet, chbind_packet_t *chbind)
+fr_pair_t *eap_chbind_packet2vp(TALLOC_CTX *ctx, chbind_packet_t *chbind)
{
fr_pair_t *vp;
if (!chbind) return NULL; /* don't produce garbage */
- MEM(vp = fr_pair_afrom_da(packet, attr_eap_channel_binding_message));
+ MEM(vp = fr_pair_afrom_da(ctx, attr_eap_channel_binding_message));
fr_pair_value_memdup(vp, (uint8_t *) chbind, talloc_array_length((uint8_t *)chbind), false);
return vp;
/* Channel binding function prototypes */
FR_CODE chbind_process(request_t *request, CHBIND_REQ *chbind_req);
-fr_pair_t *eap_chbind_packet2vp(fr_radius_packet_t *packet, chbind_packet_t *chbind);
+fr_pair_t *eap_chbind_packet2vp(TALLOC_CTX *ctx, chbind_packet_t *chbind);
chbind_packet_t *eap_chbind_vp2packet(TALLOC_CTX *ctx, fr_pair_list_t *vps);
* in the SIM/AKA/AKA' dict.
*/
while (p < end) {
- ret = fr_aka_sim_decode_pair(request->packet, decoded, dict, p, end - p, decoder_ctx);
+ ret = fr_aka_sim_decode_pair(request->request_ctx, decoded, dict, p, end - p, decoder_ctx);
if (ret <= 0) {
RPEDEBUG("Failed decoding AT");
error:
{
fr_pair_t *vp;
- vp = fr_pair_afrom_child_num(request->packet, fr_dict_root(dict), FR_SUBTYPE);
+ vp = fr_pair_afrom_child_num(request->request_ctx, fr_dict_root(dict), FR_SUBTYPE);
if (!vp) {
fr_strerror_const("Failed allocating subtype attribute");
goto error;
* fancy, just copy Identity -> Permanent-Identity.
*/
if (!strip_hint) {
- MEM(fr_pair_update_by_da(request->state_ctx, &vp,
- &request->state_pairs, attr_eap_aka_sim_permanent_identity) >= 0);
+ MEM(fr_pair_update_by_da(request->session_state_ctx, &vp,
+ &request->session_state_pairs, attr_eap_aka_sim_permanent_identity) >= 0);
fr_pair_value_bstrndup(vp, in->vp_strvalue, in->vp_length, true);
return 0;
}
*/
if ((fr_aka_sim_id_type(&our_type, &our_method, in->vp_strvalue, in->vp_length) < 0) ||
(our_type != AKA_SIM_ID_TYPE_PERMANENT)) {
- MEM(fr_pair_update_by_da(request->state_ctx, &vp,
- &request->state_pairs, attr_eap_aka_sim_permanent_identity) >= 0);
+ MEM(fr_pair_update_by_da(request->session_state_ctx, &vp,
+ &request->session_state_pairs, attr_eap_aka_sim_permanent_identity) >= 0);
fr_pair_value_bstrndup(vp, in->vp_strvalue, in->vp_length, true);
RDEBUG2("%s has incorrect hint byte, expected '%c', got '%c'. "
* Strip off the hint byte, and then add the permanent
* identity to the output list.
*/
- MEM(fr_pair_update_by_da(request->state_ctx, &vp,
- &request->state_pairs, attr_eap_aka_sim_permanent_identity) >= 0);
+ MEM(fr_pair_update_by_da(request->session_state_ctx, &vp,
+ &request->session_state_pairs, attr_eap_aka_sim_permanent_identity) >= 0);
fr_pair_value_bstrndup(vp, in->vp_strvalue + 1, in->vp_length - 1, true);
RDEBUG2("Stripping 'hint' byte from %s", attr_eap_aka_sim_permanent_identity->name);
* state increment by 1, otherwise, add the
* attribute and set to zero.
*/
- vp = fr_pair_find_by_da(&request->state_pairs, attr_eap_aka_sim_counter);
+ vp = fr_pair_find_by_da(&request->session_state_pairs, attr_eap_aka_sim_counter);
if (vp) {
vp->vp_uint16++;
/*
*/
case FR_EAP_METHOD_SIM:
case FR_EAP_METHOD_AKA:
- if (fr_aka_sim_vector_gsm_umts_kdf_0_reauth_from_attrs(request, &request->state_pairs,
+ if (fr_aka_sim_vector_gsm_umts_kdf_0_reauth_from_attrs(request, &request->session_state_pairs,
&eap_aka_sim_session->keys) != 0) {
request_new_id:
switch (eap_aka_sim_session->last_id_req) {
case FR_EAP_METHOD_AKA_PRIME:
switch (eap_aka_sim_session->kdf) {
case FR_KDF_VALUE_PRIME_WITH_CK_PRIME_IK_PRIME:
- if (fr_aka_sim_vector_umts_kdf_1_reauth_from_attrs(request, &request->state_pairs,
+ if (fr_aka_sim_vector_umts_kdf_1_reauth_from_attrs(request, &request->session_state_pairs,
&eap_aka_sim_session->keys) != 0) {
goto request_new_id;
}
if (fr_heap_num_elements(worker->time_order) >= (uint32_t) worker->config.max_requests) goto nak;
- ctx = request = request_alloc(NULL);
+ ctx = request = request_alloc(NULL, NULL);
if (!request) goto nak;
worker_request_init(worker, request, now);
*/
int server_init(CONF_SECTION *cs)
{
+ /*
+ * Load dictionary attributes used
+ * for requests.
+ */
+ if (request_global_init() < 0) return -1;
+
/*
* Initialise the trigger rate limiting tree
*/
*/
void server_free(void)
{
- /*
- * Free password dictionaries
- */
- password_free();
/*
* Free xlat instance data, and call any detach methods
*/
xlat_free();
+ /*
+ * Free password dictionaries
+ */
+ password_free();
+
/*
* The only maps remaining are the ones registered by the server core.
*/
*/
trigger_exec_free();
+ /*
+ * Free the internal dictionaries the request uses
+ */
+ request_global_free();
}
/*
* Create the virtual check item.
*/
- MEM(virt = fr_pair_afrom_da(request, tmpl_da(map->lhs)));
+ MEM(virt = fr_pair_afrom_da(request->request_ctx, tmpl_da(map->lhs)));
virt->op = map->op;
fr_value_box_copy(virt, &virt->data, rhs);
return -1;
}
- MEM(vp = fr_pair_afrom_da(request, tmpl_da(map->lhs)));
+ MEM(vp = fr_pair_afrom_da(request->request_ctx, tmpl_da(map->lhs)));
vp->op = c->data.map->op;
fr_value_box_copy(vp, &vp->data, rhs);
return;
}
- fr_pair_list_copy(request, &args, &ef->trigger_args);
+ fr_pair_list_copy(request ? request->request_ctx : NULL, &args, &ef->trigger_args);
fr_cursor_init(&cursor, &args);
MEM(vp = fr_pair_afrom_da(NULL, da));
* - 0 on success.
* - -1 on failure.
*/
-#define pair_add_request(_attr, _da) fr_pair_add_by_da(request->packet, _attr, &request->request_pairs, _da)
+#define pair_add_request(_attr, _da) fr_pair_add_by_da(request->request_ctx, _attr, &request->request_pairs, _da)
/** Allocate a fr_pair_t in the reply list
*
* - 0 on success.
* - -1 on failure.
*/
-#define pair_add_reply(_attr, _da) fr_pair_add_by_da(request->reply, _attr, &request->reply_pairs, _da)
+#define pair_add_reply(_attr, _da) fr_pair_add_by_da(request->reply_ctx, _attr, &request->reply_pairs, _da)
/** Allocate a fr_pair_t in the control list
*
* - 0 on success.
* - -1 on failure.
*/
-#define pair_add_control(_attr, _da) fr_pair_add_by_da(request, _attr, &request->control_pairs, _da)
+#define pair_add_control(_attr, _da) fr_pair_add_by_da(request->control_ctx, _attr, &request->control_pairs, _da)
/** Allocate a fr_pair_t in the session-state list
*
* - 0 on success.
* - -1 on failure.
*/
-#define pair_add_session_state(_attr, _da) fr_pair_add_by_da(request->state_ctx, _attr, &request->state_pairs, _da)
+#define pair_add_session_state(_attr, _da) fr_pair_add_by_da(request->session_state_ctx, _attr, &request->session_state_pairs, _da)
/** Return or allocate a fr_pair_t in the request list
*
* - 0 if we allocated a new attribute.
* - -1 on failure.
*/
-#define pair_update_request(_attr, _da) fr_pair_update_by_da(request->packet, _attr, &request->request_pairs, _da)
+#define pair_update_request(_attr, _da) fr_pair_update_by_da(request->request_ctx, _attr, &request->request_pairs, _da)
/** Return or allocate a fr_pair_t in the reply list
*
* - 0 if we allocated a new attribute.
* - -1 on failure.
*/
-#define pair_update_reply(_attr, _da) fr_pair_update_by_da(request->reply, _attr, &request->reply_pairs, _da)
+#define pair_update_reply(_attr, _da) fr_pair_update_by_da(request->reply_ctx, _attr, &request->reply_pairs, _da)
/** Return or allocate a fr_pair_t in the control list
*
* - 0 if we allocated a new attribute.
* - -1 on failure.
*/
-#define pair_update_control(_attr, _da) fr_pair_update_by_da(request, _attr, &request->control_pairs, _da)
+#define pair_update_control(_attr, _da) fr_pair_update_by_da(request->control_ctx, _attr, &request->control_pairs, _da)
/** Return or allocate a fr_pair_t in the session_state list
*
* - 0 if we allocated a new attribute.
* - -1 on failure.
*/
-#define pair_update_session_state(_attr, _da) fr_pair_update_by_da(request->state_ctx, _attr, &request->state_pairs, _da)
+#define pair_update_session_state(_attr, _da) fr_pair_update_by_da(request->session_state_ctx, _attr, &request->session_state_pairs, _da)
/** Delete a fr_pair_t in a list
*
* - >0 the number of pairs deleted.
* - 0 if no pairs were deleted.
*/
-#define pair_delete_session_state(_pair) pair_delete(&request->state_pairs, _pair)
+#define pair_delete_session_state(_pair) pair_delete(&request->session_state_pairs, _pair)
#endif
#include <freeradius-devel/util/acutest.h>
+#include <freeradius-devel/util/acutest_helpers.h>
#include <freeradius-devel/util/conf.h>
#include <freeradius-devel/util/dict.h>
if (!fr_dict_global_ctx_init(autofree, dict_dir)) goto error;
+ /*
+ * Initialise attributes that go in requests
+ */
+ if (request_global_init() < 0) goto error;
+
/*
* Set the root name of the dictionary
*/
/* Initialize the "sample_pairs" list */
if (load_attr_pairs(&sample_pairs) < 0) goto error;
+
+
}
static request_t *request_fake_alloc(void)
/*
* Create and initialize the new request.
*/
- request = request_local_alloc(autofree);
+ request = request_local_alloc(autofree, NULL);
request->packet = fr_radius_packet_alloc(request, false);
TEST_CHECK(request->packet != NULL);
*/
static void test_pair_add_request(void)
{
- fr_pair_t *local_pairs;
+ fr_pair_t *local_pair;
fr_cursor_t cursor;
fr_pair_t *vp;
request_t *request = request_fake_alloc();
- fr_pair_list_init(&local_pairs);
-
TEST_CASE("Add 'Test-Integer' in 'request_pairs' using pair_add_request()");
- TEST_CHECK(pair_add_request(&local_pairs, attr_test_integer) == 0);
+ TEST_CHECK(pair_add_request(&local_pair, attr_test_integer) == 0);
TEST_CASE("Validating VP_VERIFY()");
TEST_CHECK((vp = fr_cursor_init(&cursor, &request->request_pairs)) != NULL);
TEST_CHECK(vp->vp_uint32 == 12345);
TEST_MSG("Expected %s == 12345", attr_test_integer->name);
- fr_pair_list_free(&local_pairs);
+ TEST_CHECK_RET(talloc_free(request), 0);
}
static void test_pair_add_reply(void)
{
- fr_pair_t *local_pairs;
+ fr_pair_t *local_vp;
fr_cursor_t cursor;
fr_pair_t *vp;
request_t *request = request_fake_alloc();
- fr_pair_list_init(&local_pairs);
-
TEST_CASE("Add 'Test-Integer' in 'reply_pairs' using pair_add_reply()");
- TEST_CHECK(pair_add_reply(&local_pairs, attr_test_integer) == 0);
+ TEST_CHECK(pair_add_reply(&local_vp, attr_test_integer) == 0);
TEST_CASE("Validating VP_VERIFY()");
TEST_CHECK((vp = fr_cursor_init(&cursor, &request->reply_pairs)) != NULL);
TEST_CHECK(vp->vp_uint32 == 12345);
TEST_MSG("Expected %s == 12345", attr_test_integer->name);
- fr_pair_list_free(&local_pairs);
+ TEST_CHECK_RET(talloc_free(request), 0);
}
static void test_pair_add_control(void)
{
- fr_pair_t *local_pairs;
+ fr_pair_t *local_vp;
fr_cursor_t cursor;
fr_pair_t *vp;
request_t *request = request_fake_alloc();
- fr_pair_list_init(&local_pairs);
-
TEST_CASE("Add 'Test-Integer' in 'control_pairs' using pair_add_control()");
- TEST_CHECK(pair_add_control(&local_pairs, attr_test_integer) == 0);
+ TEST_CHECK(pair_add_control(&local_vp, attr_test_integer) == 0);
TEST_CASE("Validating VP_VERIFY()");
TEST_CHECK((vp = fr_cursor_init(&cursor, &request->control_pairs)) != NULL);
TEST_CHECK(vp->vp_uint32 == 12345);
TEST_MSG("Expected %s == 12345", attr_test_integer->name);
- fr_pair_list_free(&local_pairs);
+ TEST_CHECK_RET(talloc_free(request), 0);
}
static void test_pair_add_session_state(void)
{
- fr_pair_t *local_pairs;
+ fr_pair_t *local_vp;
fr_cursor_t cursor;
fr_pair_t *vp;
request_t *request = request_fake_alloc();
- fr_pair_list_init(&local_pairs);
-
TEST_CASE("Add 'Test-Integer' in 'control_pairs' using pair_add_session_state()");
- TEST_CHECK(pair_add_session_state(&local_pairs, attr_test_integer) == 0);
+ TEST_CHECK(pair_add_session_state(&local_vp, attr_test_integer) == 0);
TEST_CASE("Validating VP_VERIFY()");
- TEST_CHECK((vp = fr_cursor_init(&cursor, &request->state_pairs)) != NULL);
+ TEST_CHECK((vp = fr_cursor_init(&cursor, &request->session_state_pairs)) != NULL);
VP_VERIFY(vp);
TEST_MSG("Set vp = 12345");
TEST_CHECK(vp->vp_uint32 == 12345);
TEST_MSG("Expected %s == 12345", attr_test_integer->name);
- fr_pair_list_free(&local_pairs);
+ TEST_CHECK_RET(talloc_free(request), 0);
}
static void test_pair_update_request(void)
* Such 'vp != NULL' just to mute clang "warning: Dereference of null pointer"
*/
TEST_CHECK(vp && vp->vp_uint32 == 112233);
+
+ TEST_CHECK_RET(talloc_free(request), 0);
}
static void test_pair_update_reply(void)
VP_VERIFY(vp);
TEST_CHECK(vp && vp->vp_uint32 == 3333);
+
+ TEST_CHECK_RET(talloc_free(request), 0);
}
static void test_pair_update_control(void)
VP_VERIFY(vp);
TEST_CHECK(vp && vp->vp_uint32 == 44444);
+
+ TEST_CHECK_RET(talloc_free(request), 0);
}
static void test_pair_update_session_state(void)
vp->vp_uint32 = 7890;
TEST_CASE("Expected attr_test_integer (vp->vp_uint32 == 7890)");
- TEST_CHECK((vp = fr_pair_find_by_da(&request->state_pairs, attr_test_integer)) != NULL);
+ TEST_CHECK((vp = fr_pair_find_by_da(&request->session_state_pairs, attr_test_integer)) != NULL);
TEST_CASE("Validating VP_VERIFY()");
VP_VERIFY(vp);
TEST_CHECK(vp && vp->vp_uint32 == 7890);
+
+ TEST_CHECK_RET(talloc_free(request), 0);
}
static void test_pair_delete_request(void)
TEST_CASE("The 'Test-Integer' shouldn't exist in 'request->request_pairs'");
TEST_CHECK(fr_pair_find_by_da(&request->request_pairs, attr_test_integer) == NULL);
+
+ TEST_CHECK_RET(talloc_free(request), 0);
}
static void test_pair_delete_reply(void)
TEST_CASE("The 'Test-Integer' shouldn't exist in 'request->reply_pairs'");
TEST_CHECK(fr_pair_find_by_da(&request->reply_pairs, attr_test_integer) == NULL);
+
+ TEST_CHECK_RET(talloc_free(request), 0);
}
static void test_pair_delete_control(void)
TEST_CASE("The 'Test-Integer' shouldn't exist in 'request->control_pairs'");
TEST_CHECK(fr_pair_find_by_da(&request->control_pairs, attr_test_integer) == NULL);
+
+ TEST_CHECK_RET(talloc_free(request), 0);
}
static void test_pair_delete_session_state(void)
request_t *request = request_fake_alloc();
TEST_CASE("Copy 'sample_pairs' into 'request->state'");
- TEST_CHECK(fr_pair_list_copy(autofree, &request->state_pairs, &sample_pairs) > 0);
+ TEST_CHECK(fr_pair_list_copy(autofree, &request->session_state_pairs, &sample_pairs) > 0);
TEST_CASE("Delete 'Test-Integer' in 'request->state' using pair_delete_session_state()");
TEST_CHECK(pair_delete_session_state(attr_test_integer) > 0);
TEST_CASE("The 'Test-Integer' shouldn't exist in 'request->state'");
- TEST_CHECK(fr_pair_find_by_da(&request->state_pairs, attr_test_integer) == NULL);
+ TEST_CHECK(fr_pair_find_by_da(&request->session_state_pairs, attr_test_integer) == NULL);
+
+ TEST_CHECK_RET(talloc_free(request), 0);
}
TEST_LIST = {
if (xlat_eval(value, sizeof(value), request, name, NULL, NULL) < 0) return 0;
- MEM(vp = fr_pair_afrom_da(request, check_item->da));
+ MEM(vp = fr_pair_afrom_da(request->request_ctx, check_item->da));
vp->op = check_item->op;
fr_pair_value_from_str(vp, value, -1, '"', false);
}
bad_header:
- MEM(new = fr_pair_afrom_da(request, def));
+ MEM(new = fr_pair_afrom_da(ctx, def));
fr_pair_value_bstrndup(new, p, end - p, true);
return new;
#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/unlang/base.h>
+static request_init_args_t default_args;
+
+static fr_dict_t const *dict_freeradius;
+
+extern fr_dict_autoload_t request_dict[];
+fr_dict_autoload_t request_dict[] = {
+ { .out = &dict_freeradius, .proto = "freeradius" },
+ { NULL }
+};
+
+fr_dict_attr_t const *request_attr_root;
+fr_dict_attr_t const *request_attr_request;
+fr_dict_attr_t const *request_attr_reply;
+fr_dict_attr_t const *request_attr_control;
+fr_dict_attr_t const *request_attr_state;
+
+extern fr_dict_attr_autoload_t request_dict_attr[];
+fr_dict_attr_autoload_t request_dict_attr[] = {
+ { .out = &request_attr_root, .name = "root", .type = FR_TYPE_GROUP, .dict = &dict_freeradius },
+ { .out = &request_attr_request, .name = "request", .type = FR_TYPE_GROUP, .dict = &dict_freeradius },
+ { .out = &request_attr_reply, .name = "reply", .type = FR_TYPE_GROUP, .dict = &dict_freeradius },
+ { .out = &request_attr_control, .name = "control", .type = FR_TYPE_GROUP, .dict = &dict_freeradius },
+ { .out = &request_attr_state, .name = "session-state", .type = FR_TYPE_GROUP, .dict = &dict_freeradius },
+ { NULL }
+};
+
/** The thread local free list
*
* Any entries remaining in the list will be freed when the thread is joined
static _Thread_local fr_dlist_head_t *request_free_list; /* macro */
#ifndef NDEBUG
-static int _state_ctx_free(TALLOC_CTX *state)
+static int _state_ctx_free(fr_pair_t *state)
{
DEBUG4("state-ctx %p freed", state);
}
#endif
+static inline void CC_HINT(always_inline) request_log_init_orphan(request_t *request)
+{
+ /*
+ * These may be changed later by request_pre_handler
+ */
+ request->log.lvl = fr_debug_lvl; /* Default to global debug level */
+ if (!request->log.dst) {
+ request->log.dst = talloc_zero(request, log_dst_t);
+ } else {
+ memset(request->log.dst, 0, sizeof(*request->log.dst));
+ }
+ request->log.dst->func = vlog_request;
+ request->log.dst->uctx = &default_log;
+}
+
+static inline void CC_HINT(always_inline) request_log_init_child(request_t *child, request_t const *parent)
+{
+ /*
+ * Copy debug information.
+ */
+ memcpy(&(child->log), &(parent->log), sizeof(child->log));
+ child->log.unlang_indent = 0; /* Apart from the indent which we reset */
+ child->log.module_indent = 0; /* Apart from the indent which we reset */
+}
+
+static inline void CC_HINT(always_inline) request_log_init_detachable(request_t *child, request_t const *parent)
+{
+ /*
+ * Ensure that we use our own version of the logging
+ * information, and not the original request one.
+ */
+ child->log.dst = talloc_zero(child, log_dst_t);
+ memcpy(child->log.dst, parent->log.dst, sizeof(*child->log.dst));
+}
+
+static inline CC_HINT(always_inline) int request_detachable_init(request_t *child, request_t *parent)
+{
+ /*
+ * Associate the child with the parent, using the child's
+ * pointer as a unique identifier. Free it if the parent
+ * goes away, but don't persist it across
+ * challenge-response boundaries.
+ */
+ if (request_data_talloc_add(parent, child, 0, request_t, child, true, true, false) < 0) return -1;
+
+ return 0;
+}
+
+static inline CC_HINT(always_inline) int request_child_init(request_t *child, request_t *parent)
+{
+ child->number = parent->child_number++;
+ child->name = talloc_typed_asprintf(child, "%s.%" PRIu64 , parent->name, child->number);
+ child->seq_start = 0; /* children always start with their own sequence */
+ child->parent = parent;
+ child->dict = parent->dict;
+ child->config = parent->config;
+ child->client = parent->client;
+
+ /*
+ * For new server support.
+ *
+ * FIXME: Key instead off of a "virtual server" data structure.
+ *
+ * FIXME: Permit different servers for inner && outer sessions?
+ */
+ child->server_cs = parent->server_cs;
+
+ child->packet = fr_radius_packet_alloc(child, true);
+ if (!child->packet) {
+ talloc_free(child);
+ return -1;
+ }
+
+ child->reply = fr_radius_packet_alloc(child, false);
+ if (!child->reply) {
+ talloc_free(child);
+ return -1;
+ }
+
+ /*
+ * Fill in the child request.
+ */
+ child->packet->socket = parent->packet->socket;
+ child->packet->socket.inet.dst_port = 0;
+ child->packet->socket.fd = -1;
+
+ /*
+ * This isn't STRICTLY required, as the child request MUST NEVER
+ * be put into the request list. However, it's still reasonable
+ * practice.
+ */
+ child->packet->id = child->number & 0xff;
+ child->packet->code = parent->packet->code;
+ child->packet->timestamp = parent->packet->timestamp;
+
+ /*
+ * Required for new identity support
+ */
+ child->listener = parent->listener;
+
+ /*
+ * Fill in the child reply, based on the child request.
+ */
+ fr_socket_addr_swap(&child->reply->socket, &child->packet->socket);
+ child->reply->id = child->packet->id;
+ child->reply->code = 0; /* UNKNOWN code */
+ child->reply->socket.fd = -1;
+
+ return 0;
+}
+
/** Setup logging and other fields for a request
*
* @param[in] file the request was allocated in.
* @param[in] line the request was allocated on.
* @param[in] request to (re)-initialise.
*/
-static void request_init(char const *file, int line, request_t *request)
+static inline CC_HINT(always_inline) int request_init(char const *file, int line,
+ request_t *request, request_init_args_t const *args)
{
+
+ *request = (request_t){
#ifndef NDEBUG
- request->magic = REQUEST_MAGIC;
+ .magic = REQUEST_MAGIC,
#endif
-
- request->request_state = REQUEST_INIT;
- request->master_state = REQUEST_ACTIVE;
+ .request_state = REQUEST_INIT,
+ .master_state = REQUEST_ACTIVE,
+ .dict = args->namespace,
+ .component = "<pre-core>",
+ .runnable_id = -1,
+ .time_order_id = -1,
+ .alloc_file = file,
+ .alloc_line = line
+ };
/*
* Initialise the stack
*/
request_data_list_init(&request->data);
- /*
- * Initialise the state_ctx
- */
- if (!request->state_ctx) {
- request->state_ctx = talloc_init_const("session-state");
+ {
+ fr_pair_t *vp = NULL, *pair_root;
+
+ /*
+ * Alloc the pair root this is a
+ * special pair which does not
+ * free its children when it is
+ * freed.
+ */
+ pair_root = fr_pair_root_afrom_da(request, request_attr_root);
+ if (unlikely(!pair_root)) return -1;
+ request->pair_root = pair_root;
+
+ /*
+ * Copy all the pair lists over into
+ * the request. We then check for
+ * the any uninitialised lists and
+ * create them locally.
+ */
+ memcpy(&request->pair_list, &args->pair_list, sizeof(request->pair_list));
+
+#define list_init(_ctx, _list) \
+ vp = fr_pair_afrom_da(_ctx, request_attr_##_list); \
+ if (unlikely(!vp)) { \
+ talloc_free(pair_root); \
+ memset(&request->pair_list, 0, sizeof(request->pair_list)); \
+ return -1; \
+ } \
+ fr_pair_add(&pair_root->children, vp); \
+ request->pair_list._list = vp;
+
+ if (!request->pair_list.request) list_init(request->pair_root, request);
+ if (!request->pair_list.reply) list_init(request->pair_root, reply);
+ if (!request->pair_list.control) list_init(request->pair_root, control);
+ if (!request->pair_list.state) {
+ list_init(NULL, state);
#ifndef NDEBUG
- talloc_set_destructor(request->state_ctx, _state_ctx_free);
+ talloc_set_destructor(request->pair_list.state, _state_ctx_free);
#endif
+ }
}
/*
- * These may be changed later by request_pre_handler
+ * Initialise packets and additional
+ * fields if this is going to be a
+ * child request.
*/
- request->log.lvl = fr_debug_lvl; /* Default to global debug level */
- if (!request->log.dst) {
- request->log.dst = talloc_zero(request, log_dst_t);
+ if (args->parent) {
+ if (request_child_init(request, args->parent) < 0) return -1;
+
+ if (args->detachable) {
+ if (request_detachable_init(request, args->parent) < 0) return -1;
+ request_log_init_detachable(request, args->parent);
+ } else {
+ request_log_init_child(request, args->parent);
+ }
} else {
- memset(request->log.dst, 0, sizeof(*request->log.dst));
+ request_log_init_orphan(request);
}
- request->log.dst->func = vlog_request;
- request->log.dst->uctx = &default_log;
-
- request->module = NULL;
- request->component = "<core>";
-
- request->seq_start = 0;
- request->runnable_id = -1;
- request->time_order_id = -1;
-
- /*
- * Where the request was allocated
- */
- request->alloc_file = file;
- request->alloc_line = line;
-
- fr_dlist_entry_init(&request->free_entry); /* Needs to be initialised properly, else bad things happen */
-
- /*
- * Initialise pair value lists
- */
- fr_pair_list_init(&request->request_pairs);
- fr_pair_list_init(&request->reply_pairs);
- fr_pair_list_init(&request->control_pairs);
- fr_pair_list_init(&request->state_pairs);
+ return 0;
}
/** Callback for freeing a request struct
* Ensure any data associated
* with the state ctx is freed.
*/
- state_ctx = request->state_ctx;
- if (request->state_ctx) {
- fr_assert(!request->parent || (request->state_ctx != request->parent->state_ctx));
- talloc_free_children(request->state_ctx);
+ state_ctx = request->session_state_ctx;
+ fr_assert(talloc_parent(state_ctx) != request); /* Should never be directly parented */
+
+ if (request->session_state_ctx) {
+ fr_assert(!request->parent || (request->session_state_ctx != request->parent->session_state_ctx));
+ talloc_free_children(request->session_state_ctx);
+ talloc_get_type_abort(request->session_state_ctx, fr_pair_t);
}
free_list = request_free_list;
/*
* Reinitialise the request
*/
+ talloc_get_type_abort(request->session_state_ctx, fr_pair_t);
+ fr_assert_msg(talloc_parent(request->session_state_ctx) == NULL, "session_state_ctx %s", talloc_get_name(talloc_parent(request->session_state_ctx)));
talloc_free_children(request);
+ talloc_get_type_abort(request->session_state_ctx, fr_pair_t);
+
memset(request, 0, sizeof(*request));
request->component = "free_list";
- request->state_ctx = state_ctx; /* Use the old, now cleared, state_ctx */
+ request->session_state_ctx = state_ctx; /* Use the old, now cleared, state_ctx */
/*
* Reinsert into the free list
fr_dlist_insert_head(free_list, request);
request_free_list = free_list;
+ talloc_get_type_abort(request->session_state_ctx, fr_pair_t);
+
+
return -1; /* Prevent free */
}
* The reason why it's OK to do this, is if the state attributes
* need to persist across requests, they will already have been
* moved to a fr_state_entry_t, with the state pointers in the
- * request being set to NULL, before the request is freed.
- *
- * Our state ctx can be the same as the parents if
- * request_data_restore_to_child() was called. That
- * function resets the childs state_ctx to be the same as
- * the parents. Adding this check here means that we
- * don't need to call request_detach() on a child which
- * will be freed immediately after the detach.
+ * request being set to NULL, before the request is freed/
*
* Note also that we do NOT call TALLOC_FREE(), which
* sets state_ctx=NULL. We don't control the order in
* If this assertion hits, it means that someone didn't
* call fr_state_store_in_parent()
*/
- if (request->state_ctx) {
- fr_assert(!request->parent || (request->state_ctx != request->parent->state_ctx));
- talloc_free(request->state_ctx);
+ if (request->session_state_ctx) {
+ fr_assert(!request->parent || (request->session_state_ctx != request->parent->session_state_ctx));
+
+ talloc_free(request->session_state_ctx);
}
#ifndef NDEBUG
talloc_free(list);
}
+static inline CC_HINT(always_inline) request_t *request_alloc_pool(TALLOC_CTX *ctx)
+{
+ request_t *request;
+
+ /*
+ * Only allocate requests in the NULL
+ * ctx. There's no scenario where it's
+ * appropriate to allocate them in a
+ * pool, and using a strict talloc
+ * hierarchy means that child requests
+ * cannot be returned to a free list
+ * and would have to be freed.
+ */
+ MEM(request = talloc_pooled_object(ctx, request_t,
+ 1 + /* Stack pool */
+ UNLANG_STACK_MAX + /* Stack Frames */
+ 2 + /* packets */
+ 10, /* extra */
+ (UNLANG_FRAME_PRE_ALLOC * UNLANG_STACK_MAX) + /* Stack memory */
+ (sizeof(fr_pair_t) * 5) + /* pair lists and root*/
+ (sizeof(fr_radius_packet_t) * 2) + /* packets */
+ 128 /* extra */
+ ));
+ fr_assert(ctx != request);
+
+ return request;
+}
+
/** Create a new request_t data structure
*
+ * @param[in] file where the request was allocated.
+ * @param[in] line where the request was allocated.
+ * @param[in] ctx to bind the request to.
+ * @param[in] args Optional arguments.
+ * @return
+ * - A request on success.
+ * - NULL on error.
*/
-request_t *_request_alloc(char const *file, int line, TALLOC_CTX *ctx)
+request_t *_request_alloc(char const *file, int line, TALLOC_CTX *ctx, request_init_args_t const *args)
{
- request_t *request;
+ request_t *request;
fr_dlist_head_t *free_list;
+ if (!args) args = &default_args;
+
/*
* Setup the free list, or return the free
* list for this thread.
request = fr_dlist_head(free_list);
if (!request) {
- /*
- * Only allocate requests in the NULL
- * ctx. There's no scenario where it's
- * appropriate to allocate them in a
- * pool, and using a strict talloc
- * hierarchy means that child requests
- * cannot be returned to a free list
- * and would have to be freed.
- */
- MEM(request = talloc_zero_pooled_object(NULL, request_t,
- 1 + /* Stack pool */
- UNLANG_STACK_MAX + /* Stack Frames */
- 2 + /* packets */
- 10, /* extra */
- (UNLANG_FRAME_PRE_ALLOC * UNLANG_STACK_MAX) + /* Stack memory */
- (sizeof(fr_radius_packet_t) * 2) + /* packets */
- 128 /* extra */
- ));
+ request = request_alloc_pool(ctx);
talloc_set_destructor(request, _request_free);
} else {
/*
fr_dlist_remove(free_list, request);
}
- request_init(file, line, request);
+ if (request_init(file, line, request, args) < 0) {
+ talloc_free(request);
+ return NULL;
+ }
+
+ /*
+ * Initialise entry in free list
+ */
+ fr_dlist_entry_init(&request->free_entry); /* Needs to be initialised properly, else bad things happen */
/*
* Bind lifetime to a parent.
return request;
}
-/** Allocate a request that's not in the free list
- *
- * This can be useful if modules need a persistent request for their own purposes
- * which needs to be outside of the normal free list, so that it can be freed
- * when the module requires, not when the thread destructor runs.
- */
-request_t *_request_local_alloc(char const *file, int line, TALLOC_CTX *ctx)
+static int _request_local_free(request_t *request)
{
- request_t *request;
-
- MEM(request = talloc_zero(ctx, request_t));
-
- request_init(file, line, request);
-
/*
- * Bind state_ctx to the request Apple
- * Instruments seems to require this to not
- * count the state_ctx as leaked.
- *
- * It's unclear if this is a genuine leak
- * the previous code used a destructor
- * to free the state_ctx.
+ * Ensure anything that might reference the request is
+ * freed before it is.
*/
- talloc_steal(request, request->state_ctx);
-
- return request;
-}
-
-static request_t *request_init_fake(char const *file, int line, request_t *request, request_t *fake)
-{
- fake->number = request->child_number++;
- fake->name = talloc_typed_asprintf(fake, "%s.%" PRIu64 , request->name, fake->number);
-
- fake->seq_start = 0; /* children always start with their own sequence */
-
- fake->parent = request;
- fake->dict = request->dict;
- fake->config = request->config;
- fake->client = request->client;
+ talloc_free_children(request);
/*
- * For new server support.
+ * state_ctx is parented separately.
*
- * FIXME: Key instead off of a "virtual server" data structure.
+ * The reason why it's OK to do this, is if the state attributes
+ * need to persist across requests, they will already have been
+ * moved to a fr_state_entry_t, with the state pointers in the
+ * request being set to NULL, before the request is freed/
*
- * FIXME: Permit different servers for inner && outer sessions?
+ * Note also that we do NOT call TALLOC_FREE(), which
+ * sets state_ctx=NULL. We don't control the order in
+ * which talloc frees the children. And the parents
+ * state_ctx pointer needs to stick around so that all of
+ * the children can check it.
+ *
+ * If this assertion hits, it means that someone didn't
+ * call fr_state_store_in_parent()
*/
- fake->server_cs = request->server_cs;
-
- fake->packet = fr_radius_packet_alloc(fake, true);
- if (!fake->packet) {
- talloc_free(fake);
- return NULL;
- }
+ if (request->session_state_ctx) {
+ fr_assert(!request->parent || (request->session_state_ctx != request->parent->session_state_ctx));
- fake->reply = fr_radius_packet_alloc(fake, false);
- if (!fake->reply) {
- talloc_free(fake);
- return NULL;
+ talloc_free(request->session_state_ctx);
}
- fake->master_state = REQUEST_ACTIVE;
-
- /*
- * Fill in the fake request.
- */
- fake->packet->socket = request->packet->socket;
- fake->packet->socket.inet.dst_port = 0;
- fake->packet->socket.fd = -1;
-
- /*
- * This isn't STRICTLY required, as the fake request MUST NEVER
- * be put into the request list. However, it's still reasonable
- * practice.
- */
- fake->packet->id = fake->number & 0xff;
- fake->packet->code = request->packet->code;
- fake->packet->timestamp = request->packet->timestamp;
-
- /*
- * Required for new identity support
- */
- fake->listener = request->listener;
-
- /*
- * Fill in the fake reply, based on the fake request.
- */
- fr_socket_addr_swap(&fake->reply->socket, &fake->packet->socket);
- fake->reply->id = fake->packet->id;
- fake->reply->code = 0; /* UNKNOWN code */
-
- /*
- * Copy debug information.
- */
- memcpy(&(fake->log), &(request->log), sizeof(fake->log));
- fake->log.unlang_indent = 0; /* Apart from the indent which we reset */
- fake->log.module_indent = 0; /* Apart from the indent which we reset */
-
- /*
- * Allocation information
- */
- fake->alloc_file = file;
- fake->alloc_line = line;
-
- return fake;
-}
-
-/*
- * Create a new request_t, based on an old one.
- *
- * This function allows modules to inject fake requests
- * into the server, for tunneled protocols like TTLS & PEAP.
- */
-request_t *_request_alloc_fake(char const *file, int line, request_t *request, fr_dict_t const *namespace)
-{
- request_t *fake;
-
- fake = request_alloc(request);
- if (!fake) return NULL;
-
- if (!request_init_fake(file, line, request, fake)) return NULL;
-
- if (namespace) fake->dict = namespace;
+#ifndef NDEBUG
+ request->magic = 0x01020304; /* set the request to be nonsense */
+#endif
- return fake;
+ return 0;
}
-
-/** Allocate a fake request which is detachable from the parent.
- * i.e. if the parent goes away, sometimes the child MAY continue to
- * run.
+/** Allocate a request that's not in the free list
*
+ * This can be useful if modules need a persistent request for their own purposes
+ * which needs to be outside of the normal free list, so that it can be freed
+ * when the module requires, not when the thread destructor runs.
*/
-request_t *_request_alloc_detachable(char const *file, int line, request_t *request, fr_dict_t const *namespace)
+request_t *_request_local_alloc(char const *file, int line, TALLOC_CTX *ctx, request_init_args_t const *args)
{
- request_t *fake;
-
- fake = _request_alloc(file, line, NULL);
- if (!fake) return NULL;
+ request_t *request;
- if (!request_init_fake(file, line, request, fake)) return NULL;
+ if (!args) args = &default_args;
- if (namespace) fake->dict = namespace;
+ request = request_alloc_pool(ctx);
+ if (request_init(file, line, request, args) < 0) return NULL;
- /*
- * Ensure that we use our own version of the logging
- * information, and not the original request one.
- */
- fake->log.dst = talloc_zero(fake, log_dst_t);
- memcpy(fake->log.dst, request->log.dst, sizeof(*fake->log.dst));
+ talloc_set_destructor(request, _request_local_free);
- /*
- * Associate the child with the parent, using the child's
- * pointer as a unique identifier. Free it if the parent
- * goes away, but don't persist it across
- * challenge-response boundaries.
- */
- if (request_data_talloc_add(request, fake, 0, request_t, fake, true, true, false) < 0) {
- talloc_free(fake);
- return NULL;
- }
-
- return fake;
+ return request;
}
/** Unlink a subrequest from its parent
*
* @note This should be used for requests in preparation for freeing them.
*
- * @param[in] fake request to unlink.
+ * @param[in] child request to unlink.
* @param[in] will_free Caller super pinky swears to free
* the request ASAP, and that it wont
* touch persistable request data,
- * request->state_ctx or request->state.
+ * request->session_state_ctx or request->state.
* @return
* - 0 on success.
* - -1 on failure.
*/
-int request_detach(request_t *fake, bool will_free)
+int request_detach(request_t *child, bool will_free)
{
- request_t *request = fake->parent;
+ request_t *request = child->parent;
fr_assert(request != NULL);
/*
* Unlink the child from the parent.
*/
- request_data_get(request, fake, 0);
+ request_data_get(request, child, 0);
/*
* Fixup any sate or persistent
* request data.
*/
- fr_state_detach(fake, will_free);
+ fr_state_detach(child, will_free);
- fake->parent = NULL;
+ child->parent = NULL;
while (!request->backlog) {
fr_assert(request->parent != NULL);
request = request->parent;
}
- fake->backlog = request->backlog;
+ child->backlog = request->backlog;
+
+ return 0;
+}
+
+int request_global_init(void)
+{
+ if (fr_dict_autoload(request_dict) < 0) {
+ PERROR("%s", __FUNCTION__);
+ return -1;
+ }
+ if (fr_dict_attr_autoload(request_dict_attr) < 0) {
+ PERROR("%s", __FUNCTION__);
+ fr_dict_autofree(request_dict);
+ return -1;
+ }
return 0;
}
+void request_global_free(void)
+{
+ fr_dict_autofree(request_dict);
+}
+
#ifdef WITH_VERIFY_PTR
/*
* Verify a packet.
*/
static void packet_verify(char const *file, int line,
- request_t const *request, fr_radius_packet_t const *packet,
- fr_pair_list_t const *list, char const *type)
+ request_t const *request, fr_radius_packet_t const *packet, char const *type)
{
TALLOC_CTX *parent;
}
PACKET_VERIFY(packet);
-
- fr_pair_list_verify(file, line, packet, list);
}
/*
"CONSISTENCY CHECK FAILED %s[%i]: expected request_t size of %zu bytes, got %zu bytes",
file, line, sizeof(request_t), talloc_get_size(request));
- fr_pair_list_verify(file, line, request, &request->control_pairs);
- fr_pair_list_verify(file, line, request->state_ctx, &request->state_pairs);
+ (void)talloc_get_type_abort(request->request_ctx, fr_pair_t);
+ fr_pair_list_verify(file, line, request->request_ctx, &request->request_pairs);
+ (void)talloc_get_type_abort(request->reply_ctx, fr_pair_t);
+ fr_pair_list_verify(file, line, request->reply_ctx, &request->reply_pairs);
+ (void)talloc_get_type_abort(request->control_ctx, fr_pair_t);
+ fr_pair_list_verify(file, line, request->control_ctx, &request->control_pairs);
+ (void)talloc_get_type_abort(request->session_state_ctx, fr_pair_t);
+ fr_assert_msg(talloc_parent(request->session_state_ctx) == NULL,
+ "session_state_ctx must not be parented by another chunk, but is parented by %s",
+ talloc_get_name(talloc_parent(request->session_state_ctx)));
+
+ fr_pair_list_verify(file, line, request->session_state_ctx, &request->session_state_pairs);
fr_assert(request->server_cs != NULL);
if (request->packet) {
- packet_verify(file, line, request, request->packet, &request->request_pairs, "request");
+ packet_verify(file, line, request, request->packet, "request");
#if 0
/*
* @todo - a multi-protocol server shouldn't have
*/
if ((request->packet->code == FR_CODE_ACCESS_REQUEST) &&
(request->reply && !request->reply->code)) {
- fr_assert(request->state_ctx != NULL);
+ fr_assert(request->session_state_ctx != NULL);
}
#endif
}
- if (request->reply) packet_verify(file, line, request, request->reply, &request->reply_pairs, "reply");
+ if (request->reply) packet_verify(file, line, request, request->reply, "reply");
if (request->async) {
(void) talloc_get_type_abort(request->async, fr_async_t);
(void) talloc_get_type_abort(rd, request_data_t);
if (request_data_persistable(rd)) {
- fr_assert(request->state_ctx);
- fr_assert(talloc_parent(rd) == request->state_ctx);
+ fr_assert(request->session_state_ctx);
+ fr_assert(talloc_parent(rd) == request->session_state_ctx);
} else {
fr_assert(talloc_parent(rd) == request);
}
typedef void (*fr_request_process_t)(request_t *, fr_state_signal_t); //!< Function handler for requests.
typedef rlm_rcode_t (*RAD_REQUEST_FUNP)(request_t *);
+extern fr_dict_attr_t const *request_attr_root;
+extern fr_dict_attr_t const *request_attr_request;
+extern fr_dict_attr_t const *request_attr_reply;
+extern fr_dict_attr_t const *request_attr_control;
+extern fr_dict_attr_t const *request_attr_state;
+
+/** Convenience macro for accessing the request list
+ *
+ * This should be used in the form `&request->request_pairs`
+ * to get a pointer to the head of the request list.
+ */
+#define request_pairs pair_list.request->children
+
+/** Talloc ctx for allocating request pairs under
+ */
+#define request_ctx pair_list.request
+
+/** Convenience macro for accessing the reply list
+ *
+ * This should be used in the form `&request->reply_pairs`
+ * to get a pointer to the head of the request list.
+ */
+#define reply_pairs pair_list.reply->children
+
+/** Talloc ctx for allocating reply pairs under
+ */
+#define reply_ctx pair_list.reply
+
+/** Convenience macro for accessing the control list
+ *
+ * This should be used in the form `&request->control_pairs`
+ * to get a pointer to the head of the request list.
+ */
+#define control_pairs pair_list.control->children
+
+/** Talloc ctx for allocating control pairs under
+ */
+#define control_ctx pair_list.control
+
+/** Convenience macro for accessing the state list
+ *
+ * This should be used in the form `&request->session_state_pairs`
+ * to get a pointer to the head of the request list.
+ */
+#define session_state_pairs pair_list.state->children
+
+/** Talloc ctx for allocating reply pairs under
+ */
+#define session_state_ctx pair_list.state
+
+/** Pair lists accessible from the request
+ *
+ */
+typedef struct {
+ fr_pair_t *request; //!< Pair containing the request list.
+ fr_pair_t *reply; //!< Pair containing the reply list.
+ fr_pair_t *control; //!< Pair containing the control list.
+ fr_pair_t *state; //!< Pair containing the state list.
+} request_pair_lists_t;
+
struct request_s {
#ifndef NDEBUG
uint32_t magic; //!< Magic number used to detect memory corruption,
//!< or request structs that have not been properly initialised.
#endif
+ void *stack; //!< unlang interpreter stack.
+
+ request_t *parent; //!< Request that generated this request.
+
uint64_t number; //!< Monotonically increasing request number. Reset on server restart.
uint64_t child_number; //!< Monotonically increasing number for children of this request
char const *name; //!< for debug printing, as (%d) is no longer sufficient
+ uint64_t seq_start; //!< State sequence ID. Stable identifier for a sequence of requests
+ //!< and responses.
+
+ fr_pair_t *pair_root; //!< Root atribute which contains the
+ ///< other list attributes as children.
+
+ /** Pair lists associated with the request
+ *
+ * @warn DO NOT allocate pairs directly beneath the root
+ * or in the ctx of the request.
+ * They MUST be allocated beneath their appropriate
+ * list attribute.
+ */
+ request_pair_lists_t pair_list; //!< Structure containing all pair lists.
+
+ /** Logging information
+ *
+ */
+ struct {
+ log_dst_t *dst; //!< First in a list of log destinations.
+
+ fr_log_lvl_t lvl; //!< Log messages with lvl >= to this should be logged.
+
+ uint8_t unlang_indent; //!< By how much to indent log messages. uin8_t so it's obvious
+ //!< when a request has been exdented too much.
+ uint8_t module_indent; //!< Indentation after the module prefix name.
+ } log;
+
fr_dict_t const *dict; //!< Dictionary of the protocol that this request belongs to.
+ fr_radius_packet_t *packet; //!< Incoming request.
+ fr_radius_packet_t *reply; //!< Outgoing response.
+
fr_event_list_t *el; //!< thread-specific event list.
fr_heap_t *backlog; //!< thread-specific backlog
request_state_t request_state; //!< state for the various protocol handlers.
rad_listen_t *listener; //!< The listener that received the request.
RADCLIENT *client; //!< The client that originally sent us the request.
- fr_radius_packet_t *packet; //!< Incoming request.
- fr_radius_packet_t *reply; //!< Outgoing response.
-
- uint64_t seq_start; //!< State sequence ID. Stable identifier for a sequence of requests
- //!< and responses.
-
- fr_pair_list_t request_list;
- fr_pair_list_t reply_list;
- fr_pair_list_t control_list; //!< #fr_pair_t list used to set per request parameters
- //!< for modules and the server core at runtime.
- TALLOC_CTX *state_ctx; //!< for request->state
- fr_pair_list_t state_list; //!< #fr_pair_t list available over the lifetime of the authentication
- //!< attempt. Useful where the attempt involves a sequence of
- //!< many request/challenge packets, like OTP, and EAP.
-
rad_master_state_t master_state; //!< Set by the master thread to signal the child that's currently
//!< working with the request, to do something.
char const *component; //!< Section the request is in.
char const *module; //!< Module the request is currently being processed by.
- void *stack; //!< unlang interpreter stack.
-
- request_t *parent;
-
fr_event_timer_t const *ev; //!< Event in event loop tied to this request.
int32_t runnable_id; //!< entry in the queue / heap of runnable packets
main_config_t const *config; //!< Pointer to the main config hack to try and deal with hup.
- struct {
- log_dst_t *dst; //!< First in a list of log destinations.
-
- fr_log_lvl_t lvl; //!< Log messages with lvl >= to this should be logged.
-
- uint8_t unlang_indent; //!< By how much to indent log messages. uin8_t so it's obvious
- //!< when a request has been exdented too much.
- uint8_t module_indent; //!< Indentation after the module prefix name.
- } log;
-
uint32_t options; //!< mainly for proxying EAP-MSCHAPv2.
fr_async_t *async; //!< for new async listeners
fr_dlist_t free_entry; //!< Request's entry in the free list.
}; /* request_t typedef */
+/** Optional arguments for initialising requests
+ *
+ */
+typedef struct {
+ fr_dict_t const *namespace; //!< The namespace this request implements.
+
+ request_t *parent; //!< If set, the request is a child request used to run
+ ///< policy sections and additional virtual servers.
+
+ request_pair_lists_t pair_list; //!< Alternative pair list heads.
+ ///< These allow a request to expose nested attributes as
+ ///< request or reply lists from the parent.
+
+ bool detachable; //!< Request should be detachable, i.e. able to run even
+ ///< if its parent exits.
+} request_init_args_t;
+
#ifdef WITH_VERIFY_PTR
# define REQUEST_VERIFY(_x) request_verify(__FILE__, __LINE__, _x)
#else
# define REQUEST_VERIFY(_x) fr_assert(_x)
#endif
-
#define RAD_REQUEST_LVL_NONE (0) //!< No debug messages should be printed.
#define RAD_REQUEST_LVL_DEBUG (1)
#define RAD_REQUEST_LVL_DEBUG2 (2)
#define RAD_REQUEST_OPTION_CTX (1 << 1)
#define RAD_REQUEST_OPTION_DETAIL (1 << 2)
-#define request_alloc(_ctx) _request_alloc( __FILE__, __LINE__, _ctx)
-request_t *_request_alloc(char const *file, int line, TALLOC_CTX *ctx);
-
-#define request_local_alloc(_ctx) _request_local_alloc(__FILE__, __LINE__, _ctx)
-request_t *_request_local_alloc(char const *file, int line, TALLOC_CTX *ctx);
+/** Allocate a new request
+ *
+ * @param[in] _ctx Talloc ctx to bind the request to.
+ * @param[in] _args Optional arguments that control how the request is initialised.
+ */
+#define request_alloc(_ctx, _args) _request_alloc( __FILE__, __LINE__, (_ctx), (_args))
+request_t *_request_alloc(char const *file, int line, TALLOC_CTX *ctx, request_init_args_t const *args);
-#define request_alloc_fake(_request, _namespace) _request_alloc_fake(__FILE__, __LINE__, _request, _namespace)
-request_t *_request_alloc_fake(char const *file, int line, request_t *parent, fr_dict_t const *namespace);
+/** Allocate a new request outside of the request pool
+ *
+ * @param[in] _ctx Talloc ctx to allocate the request in.
+ * @param[in] _args Optional arguments that control how the request is initialised.
+ */
+#define request_local_alloc(_ctx, _args) _request_local_alloc(__FILE__, __LINE__, (_ctx), (_args))
+request_t *_request_local_alloc(char const *file, int line, TALLOC_CTX *ctx, request_init_args_t const *args);
-#define request_alloc_detachable(_request, _namespace) _request_alloc_detachable(__FILE__, __LINE__, _request, _namespace)
-request_t *_request_alloc_detachable(char const *file, int line, request_t *request, fr_dict_t const *namespace);
+int request_detach(request_t *child, bool will_free);
-int request_detach(request_t *fake, bool will_free);
+int request_global_init(void);
+void request_global_free(void);
#ifdef WITH_VERIFY_PTR
void request_verify(char const *file, int line, request_t const *request); /* only for special debug builds */
* Request must have a state ctx
*/
fr_assert(request);
- fr_assert(!persist || request->state_ctx);
+ fr_assert(!persist || request->session_state_ctx);
fr_assert(!persist ||
- (talloc_parent(opaque) == request->state_ctx) ||
+ (talloc_parent(opaque) == request->session_state_ctx) ||
(talloc_parent(opaque) == talloc_null_ctx()));
fr_assert(!free_on_parent || (talloc_parent(opaque) != request));
*/
if (!rd) {
if (persist) {
- fr_assert(request->state_ctx);
- rd = request_data_alloc(request->state_ctx);
+ fr_assert(request->session_state_ctx);
+ rd = request_data_alloc(request->session_state_ctx);
} else {
rd = request_data_alloc(request);
}
request_data_list_dump(request, &request->data);
}
-
-/** Free any subrequest request data if the dlist head is freed
- *
- */
-static int _free_child_data(fr_dlist_head_t *head)
-{
- request_data_t *rd = NULL, *prev;
-
- while ((rd = fr_dlist_next(head, rd))) {
- prev = fr_dlist_remove(head, rd);
- talloc_free(rd);
- rd = prev;
- }
-
- return 0;
-}
-
-/** Store persistable data from a subrequest in its parent
- *
- * @note #request_data_restore_to_child should have been called
- * on the request before any request data is added to it,
- * so that the state_ctx is set correctly.
- *
- * @param[in] request The child request to retrieve state from.
- * @param[in] unique_ptr A parent may have multiple subrequests spawned
- * by different modules. This identifies the module
- * or other facility that spawned the subrequest.
- * @param[in] unique_int Further identification.
- * @return
- * - 0 on success.
- * - <0 on failure.
- */
-int request_data_store_in_parent(request_t *request, void const *unique_ptr, int unique_int)
-{
- fr_dlist_head_t *child_list;
-
- if (!fr_cond_assert_msg((request->state_ctx == request->parent->state_ctx),
- "Child's state_ctx (%p), differs from parent's (%p). "
- "Unbalanced calls to request_data_restore_to_child/request_data_store_in_parent or "
- "request_data_restore_to_child never called",
- request->state_ctx, request->parent->state_ctx)) return -1;
-
- /*
- * Move child request data back into its
- * parent.
- */
- if (request_data_by_persistance_count(request, true) > 0) {
- MEM(child_list = talloc_zero(request->parent->state_ctx, fr_dlist_head_t));
- fr_dlist_talloc_init(child_list, request_data_t, list);
- talloc_set_destructor(child_list, _free_child_data);
-
- /*
- * Pull everything out of the child,
- * add it to our temporary list head...
- */
- request_data_by_persistance(child_list, request, true);
-
- /*
- * ...and add the request_data from
- * the child back into the parent.
- */
- request_data_talloc_add(request->parent, unique_ptr, unique_int,
- fr_dlist_head_t, child_list, true, false, true);
- }
-
- /*
- * Ensure request_data_restore_to_child
- * can be called again if it's actually
- * needed, by giving the child it's own
- * unique state_ctx again.
- */
- MEM(request->state_ctx = talloc_init_const("session-state"));
-
- return 0;
-}
-
-/** Restore subrequest data from a parent request
- *
- * @param[in] request The child request to restore state to.
- * @param[in] unique_ptr A parent may have multiple subrequests spawned
- * by different modules. This identifies the module
- * or other facility that spawned the subrequest.
- * @param[in] unique_int Further identification.
- * @return
- * - 0 on success.
- * - <0 on failure.
- */
-int request_data_restore_to_child(request_t *request, void const *unique_ptr, int unique_int)
-{
- fr_dlist_head_t *head;
-
- /*
- * All requests are alloced with a state_ctx.
- * In this case, nothing should be parented
- * off it already, so we can just free it.
- */
- if (!fr_cond_assert_msg((talloc_get_size(request->state_ctx) == 0),
- "Child's state_ctx must contain no "
- "allocations when restoring data from a parent")) return -1;
-
- /*
- * If the parent and child state_ctxs are the
- * same, then it means this function has been
- * called before, without request_data_store_in_parent
- * being called afterwards.
- */
- if (!fr_cond_assert_msg((request->state_ctx != request->parent->state_ctx),
- "Child's state_ctx must not be equal to its parent's state_ctx. "
- "Unbalanced calls to request_data_restore_to_child/request_data_store_in_parent"))
- return -1;
-
- /*
- * Destroy the child's state_ctx and have it
- * use its parent's.
- */
- TALLOC_FREE(request->state_ctx);
- request->state_ctx = request->parent->state_ctx; /* Use top level state ctx */
-
- head = request_data_get(request->parent, unique_ptr, unique_int);
- if (!head) return 0;
-
- request_data_restore(request, head);
- talloc_free(head);
-
- return 0;
-}
-
#ifdef WITH_VERIFY_PTR
bool request_data_persistable(request_data_t *rd)
{
void request_data_dump(request_t *request);
-int request_data_store_in_parent(request_t *request, void const *unique_ptr, int unique_int);
-
-int request_data_restore_to_child(request_t *request, void const *unique_ptr, int unique_int);
-
#ifdef WITH_VERIFY_PTR
bool request_data_persistable(request_data_t *rd);
return -(depth);
}
- MEM(vp = fr_pair_afrom_da(request->reply, da));
+ MEM(vp = fr_pair_afrom_da(request->reply_ctx, da));
vp->vp_uint32 = i;
fr_cursor_prepend(out, vp);
*/
if (map_p->get(request->reply, &data, map_p, snmp_ctx) < 0) goto error;
- MEM(vp = fr_pair_afrom_da(request->reply, map_p->da));
+ MEM(vp = fr_pair_afrom_da(request->reply_ctx, map_p->da));
fr_value_box_steal(vp, &vp->data, &data);
fr_cursor_append(out, vp);
- MEM(vp = fr_pair_afrom_da(request->reply, attr_snmp_type));
+ MEM(vp = fr_pair_afrom_da(request->reply_ctx, attr_snmp_type));
vp->vp_uint32 = map_p->type;
fr_cursor_append(out, vp);
}
ssize_t ret;
if (!map_p->set || (map_p->type == FR_FREERADIUS_SNMP_TYPE_OBJECT)) {
- MEM(vp = fr_pair_afrom_da(request->reply, attr_snmp_failure));
+ MEM(vp = fr_pair_afrom_da(request->reply_ctx, attr_snmp_failure));
vp->vp_uint32 = FR_FREERADIUS_SNMP_FAILURE_VALUE_NOT_WRITABLE;
fr_cursor_append(out, vp);
return 0;
case FR_FREERADIUS_SNMP_FAILURE_VALUE_WRONG_LENGTH:
case FR_FREERADIUS_SNMP_FAILURE_VALUE_WRONG_VALUE:
case FR_FREERADIUS_SNMP_FAILURE_VALUE_INCONSISTENT_VALUE:
- MEM(vp = fr_pair_afrom_da(request->reply, attr_snmp_failure));
+ MEM(vp = fr_pair_afrom_da(request->reply_ctx, attr_snmp_failure));
vp->vp_uint32 = -(ret);
fr_cursor_append(out, vp);
break;
RCSID("$Id$")
#include <freeradius-devel/server/base.h>
+#include <freeradius-devel/server/request.h>
#include <freeradius-devel/server/state.h>
-#include <freeradius-devel/util/debug.h>
+#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/util/dlist.h>
#include <freeradius-devel/util/md5.h>
#include <freeradius-devel/util/misc.h>
int tries;
- TALLOC_CTX *ctx; //!< ctx to parent any data that needs to be
- //!< tied to the lifetime of the request progression.
- fr_pair_t *vps; //!< session-state fr_pair_ts, parented by ctx.
+ fr_pair_t *ctx; //!< for all session specific data.
fr_dlist_head_t data; //!< Persistable request data, also parented by ctx.
- request_t *thawed; //!< The request that thawed this entry.
+ request_t *thawed; //!< The request that thawed this entry.
} fr_state_entry_t;
+/** A child of a fr_state_entry_t
+ *
+ * Children are tracked using the request data of parents.
+ *
+ * request data is added with identifiers that uniquely identify the
+ * subrequest it should be restored to.
+ *
+ * In this way a top level fr_state_entry_t can hold the session
+ * information for multiple children, and the children may hold
+ * state_child_entry_ts for grandchildren.
+ */
+typedef struct {
+ fr_pair_t *ctx; //!< for all session specific data.
+
+ fr_dlist_head_t data; //!< Persistable request data, also parented by ctx.
+
+ request_t *thawed; //!< The request that thawed this entry.
+} state_child_entry_t;
+
struct fr_state_tree_s {
uint64_t id; //!< Next ID to assign.
uint64_t timed_out; //!< Number of states that were cleaned up due to
* by the state context.
*/
if (entry->ctx) {
- for (vp = fr_cursor_init(&cursor, &entry->vps);
+ for (vp = fr_cursor_init(&cursor, &entry->ctx->children);
vp;
vp = fr_cursor_next(&cursor)) {
fr_assert(entry->ctx == talloc_parent(vp));
* Allocation doesn't need to occur inside the critical region
* and would add significantly to contention.
*/
- entry = talloc_zero(NULL, fr_state_entry_t);
- if (!entry) {
- PTHREAD_MUTEX_LOCK(&state->mutex); /* Caller expects this to be locked */
- return NULL;
- }
+ MEM(entry = talloc_zero(NULL, fr_state_entry_t));
request_data_list_init(&entry->data);
talloc_set_destructor(entry, _state_entry_free);
*/
entry->state_comp.server_id = state->server_id;
- MEM(vp = fr_pair_afrom_da(request, state->da));
+ MEM(vp = fr_pair_afrom_da(request->reply_ctx, state->da));
fr_pair_value_memdup(vp, entry->state, sizeof(entry->state), false);
fr_pair_add(reply_list, vp);
}
* stupid like add additional session-state attributes
* in one of the later sections.
*/
- TALLOC_FREE(request->state_ctx);
- request->state_pairs = NULL;
+ TALLOC_FREE(request->session_state_ctx);
- MEM(request->state_ctx = talloc_init_const("session-state"));
+ MEM(request->session_state_ctx = fr_pair_afrom_da(NULL, request_attr_state));
RDEBUG3("%s - discarded", state->da->name);
TALLOC_CTX *old_ctx = NULL;
fr_pair_t *vp;
- fr_assert(request->state_pairs == NULL);
-
/*
* No State, don't do anything.
*/
PTHREAD_MUTEX_UNLOCK(&state->mutex);
return;
}
- if (request->state_ctx) old_ctx = request->state_ctx; /* Store for later freeing */
+ if (request->session_state_ctx) old_ctx = request->session_state_ctx; /* Store for later freeing */
fr_assert(entry->ctx);
request->seq_start = entry->seq_start;
- request->state_ctx = entry->ctx;
- request->state_pairs = entry->vps;
+ request->session_state_ctx = entry->ctx;
request_data_restore(request, &entry->data);
entry->ctx = NULL;
- entry->vps = NULL;
entry->thawed = request;
}
PTHREAD_MUTEX_UNLOCK(&state->mutex);
- if (request->state_pairs) {
+ if (request->session_state_pairs) {
RDEBUG2("Restored &session-state");
- log_request_pair_list(L_DBG_LVL_2, request, NULL, &request->state_pairs, "&session-state.");
+ log_request_pair_list(L_DBG_LVL_2, request, NULL, &request->session_state_pairs, "&session-state.");
}
/*
/** Transfer ownership of the state fr_pair_ts and ctx, back to a state entry
*
- * Put request->state_pairs into the State attribute. Put the State attribute
+ * Put request->session_state_pairs into the State attribute. Put the State attribute
* into the vps list. Delete the original entry, if it exists
*
* Also creates a new state entry.
request_data_list_init(&data);
request_data_by_persistance(&data, request, true);
- if (!request->state_pairs && fr_dlist_empty(&data)) return 0;
+ if (!request->session_state_pairs && fr_dlist_empty(&data)) return 0;
- if (request->state_pairs) {
+ if (request->session_state_pairs) {
RDEBUG2("Saving &session-state");
- log_request_pair_list(L_DBG_LVL_2, request, NULL, &request->state_pairs, "&session-state.");
+ log_request_pair_list(L_DBG_LVL_2, request, NULL, &request->session_state_pairs, "&session-state.");
}
vp = fr_pair_find_by_da(&request->request_pairs, state->da);
}
fr_assert(entry->ctx == NULL);
- fr_assert(request->state_ctx);
+ fr_assert(request->session_state_ctx);
entry->seq_start = request->seq_start;
- entry->ctx = request->state_ctx;
- entry->vps = request->state_pairs;
+ entry->ctx = request->session_state_ctx;
fr_dlist_move(&entry->data, &data);
- request->state_ctx = NULL;
- request->state_pairs = NULL;
+ request->session_state_ctx = NULL;
PTHREAD_MUTEX_UNLOCK(&state->mutex);
return 0;
}
+/** Free any subrequest request data if the dlist head is freed
+ *
+ */
+static int _free_child_data(state_child_entry_t *child_entry)
+{
+ fr_dlist_talloc_free(&child_entry->data);
+
+ return 0;
+}
+
/** Store subrequest's session-state list and persistable request data in its parent
*
- * @param[in] request The child request to retrieve state from.
+ * @param[in] child The child request to retrieve state from.
* @param[in] unique_ptr A parent may have multiple subrequests spawned
* by different modules. This identifies the module
* or other facility that spawned the subrequest.
* @param[in] unique_int Further identification.
*/
-void fr_state_store_in_parent(request_t *request, void const *unique_ptr, int unique_int)
+void fr_state_store_in_parent(request_t *child, void const *unique_ptr, int unique_int)
{
- if (!fr_cond_assert_msg(request->parent,
+ state_child_entry_t *child_entry;
+ request_t *request = child; /* Stupid logging */
+
+ if (!fr_cond_assert_msg(child->parent,
"Child request must have request->parent set when storing state")) return;
- RDEBUG3("Storing subrequest state in request %s", request->parent->name);
+ RDEBUG3("Storing subrequest state in request %s", child->parent->name);
+
+ if ((request_data_by_persistance_count(request, true) > 0) ||
+ !fr_pair_list_empty(&request->session_state_pairs)) {
+ MEM(child_entry = talloc_zero(request->parent->session_state_ctx, state_child_entry_t));
+ request_data_list_init(&child_entry->data);
+ talloc_set_destructor(child_entry, _free_child_data);
+
+ /*
+ * Pull everything out of the child,
+ * add it to our temporary list head...
+ *
+ * request_data_add allocs persistable
+ * request dta in the session_state_ctx
+ * which is why we don't need to copy or
+ * reparent any of this.
+ */
+ request_data_by_persistance(&child_entry->data, request, true);
- /*
- * Shove this into the child to make
- * it easier to store/restore the
- * whole lot...
- */
- if (request->state_pairs) {
/*
- * If parent and child share a state_ctx
- * which they usually should do, then just
- * add the state list into request_data_t
- * and don't bother copying.
+ * ...and add the request_data from
+ * the child back into the parent.
*/
- request_data_talloc_add(request, (void *)fr_state_store_in_parent, 0, fr_pair_t,
- request->state_pairs, true, false, true);
- request->state_pairs = NULL;
+ request_data_talloc_add(request->parent, unique_ptr, unique_int,
+ state_child_entry_t, child_entry, true, false, true);
}
/*
- * Contains asserts to protect against
- * Unbalanced or out of order calls to
- * fr_state_store_in_parent and fr_state_restore_to_child.
+ * Ensure fr_state_restore_to_child
+ * can be called again if it's actually
+ * needed, by giving the child it's own
+ * unique state_ctx again.
*/
- if (request_data_store_in_parent(request, unique_ptr, unique_int) < 0) {
- request->state_pairs = request_data_get(request, (void *)fr_state_store_in_parent, 0);
- return;
- }
+ MEM(request->session_state_ctx = fr_pair_afrom_da(NULL, request_attr_state));
}
/** Restore subrequest data from a parent request
*
- * @param[in] request The child request to restore state to.
+ * @param[in] child The child request to restore state to.
* @param[in] unique_ptr A parent may have multiple subrequests spawned
* by different modules. This identifies the module
* or other facility that spawned the subrequest.
* @param[in] unique_int Further identification.
*/
-void fr_state_restore_to_child(request_t *request, void const *unique_ptr, int unique_int)
+void fr_state_restore_to_child(request_t *child, void const *unique_ptr, int unique_int)
{
- if (!fr_cond_assert_msg(request->parent,
+ state_child_entry_t *child_entry;
+ request_t *request = child; /* Stupid logging */
+
+ if (!fr_cond_assert_msg(child->parent,
"Child request must have request->parent set when restoring state")) return;
- RDEBUG3("Restoring subrequest state from request %s", request->parent->name);
+
+ child_entry = request_data_get(child->parent, unique_ptr, unique_int);
+ if (!child_entry) {
+ RDEBUG3("No child state found in parent %s", child->parent->name);
+ return;
+ }
/*
- * Contains asserts to protect against
- * Unbalanced or out of order calls to
- * fr_state_store_in_parent and fr_state_restore_to_child.
+ * Shouldn't really be possible unless
+ * there's a logic bug in this API.
*/
- if (request_data_restore_to_child(request, unique_ptr, unique_int) < 0) return;
+ if (!fr_cond_assert_msg(!child_entry->thawed,
+ "Child state entry already thawed by %s - %p",
+ child_entry->thawed->name, child_entry->thawed)) return;
+
+ RDEBUG3("Restoring subrequest state from request %s", child->parent->name);
/*
- * Get the state vps back
+ * If we can restore from the parent, do so
*/
- request->state_pairs = request_data_get(request, (void *)fr_state_store_in_parent, 0);
+ TALLOC_FREE(child->session_state_ctx);
+ child->session_state_ctx = child_entry->ctx;
+ child_entry->ctx = NULL; /* No longer owns the ctx */
+ child_entry->thawed = child;
+
+ request_data_restore(child, &child_entry->data); /* Put all the request data back */
+
+ talloc_free(child_entry);
}
/** Move all request data and session-state VPs into a new state_ctx
* @param[in] will_free Caller super pinky swears to free
* the request ASAP, and that it wont
* touch persistable request data,
- * request->state_ctx or request->state.
+ * request->session_state_ctx or request->state.
*/
void fr_state_detach(request_t *request, bool will_free)
{
- fr_pair_list_t vps;
- TALLOC_CTX *new_state_ctx;
-
- fr_pair_list_init(&vps);
- if (unlikely(request->parent == NULL)) return;
+ fr_pair_t *new_state_ctx;
if (will_free) {
- fr_pair_list_free(&request->state_pairs);
+ fr_pair_list_free(&request->session_state_pairs);
/*
* The non-persistable stuff is
* prented directly by the request
*/
request_data_persistable_free(request);
-
- /*
- * Parent will take care of freeing
- * honestly this should probably
- * be an assert.
- */
- if (request->state_ctx == request->parent->state_ctx) request->state_ctx = NULL;
return;
}
- MEM(new_state_ctx = talloc_init_const("session-state"));
+ /*
+ * Alloc a new pairlist to use as the
+ * state ctx and the head of the
+ * state list.
+ */
+ MEM(new_state_ctx = fr_pair_afrom_da(NULL, request_attr_state));
request_data_by_persistance_reparent(new_state_ctx, NULL, request, true);
request_data_by_persistance_reparent(new_state_ctx, NULL, request, false);
- (void) fr_pair_list_copy(new_state_ctx, &vps, &request->state_pairs);
- fr_pair_list_free(&request->state_pairs);
+ (void) fr_pair_list_copy(new_state_ctx, &new_state_ctx->children, &request->session_state_pairs);
+ fr_pair_list_free(&request->session_state_pairs);
- request->state_pairs = vps;
-
- /*
- * ...again, should probably
- * not happen and should probably
- * be an assert.
- */
- if (request->state_ctx != request->parent->state_ctx) talloc_free(request->state_ctx);
- request->state_ctx = new_state_ctx;
+ request->session_state_ctx = new_state_ctx;
}
/** Return number of entries created
return &request->control_pairs;
case PAIR_LIST_STATE:
- return &request->state_pairs;
+ return &request->session_state_pairs;
}
RWDEBUG2("List \"%s\" is not available",
switch (list) {
case PAIR_LIST_REQUEST:
- return request->packet;
+ return request->request_ctx;
case PAIR_LIST_REPLY:
- return request->reply;
+ return request->reply_ctx;
case PAIR_LIST_CONTROL:
- return request;
+ return request->control_ctx;
case PAIR_LIST_STATE:
- return request->state_ctx;
+ return request->session_state_ctx;
/* Don't add default */
case PAIR_LIST_UNKNOWN:
/*
* Bootstrap these for simpliciy.
*/
- (void) fr_pair_list_copy(request->packet, &request->request_pairs, &ctx->vps);
+ (void) fr_pair_list_copy(request->request_ctx, &request->request_pairs, &ctx->vps);
if (unlang_interpret_push_instruction(request, NULL,
RLM_MODULE_REJECT, UNLANG_TOP_FRAME) < 0) {
/*
* radius_exec_program always needs a request.
*/
- fake = request_alloc(NULL);
+ fake = request_alloc(NULL, NULL);
memcpy(&fake->server_cs, &subcs, sizeof(subcs)); /* completely wrong, but we need to use _something_ */
/*
/*
* Put the SSL data into an attribute.
*/
- MEM(vp = fr_pair_afrom_da(request->state_ctx, attr_tls_session_data));
+ MEM(vp = fr_pair_afrom_da(request->session_state_ctx, attr_tls_session_data));
fr_pair_value_memdup(vp, tls_session->session_blob, talloc_array_length(tls_session->session_blob), false);
RINDENT();
RDEBUG2("&session-state.%pP", vp);
REXDENT();
- fr_pair_add(&request->state_pairs, vp);
+ fr_pair_add(&request->session_state_pairs, vp);
/*
* Call the virtual server to write the session
/*
* Ensure that the session data can't be used by anyone else.
*/
- fr_pair_delete_by_da(&request->state_pairs, attr_tls_session_data);
+ fr_pair_delete_by_da(&request->session_state_pairs, attr_tls_session_data);
return ret;
}
return NULL;
}
- vp = fr_pair_find_by_da(&request->state_pairs, attr_tls_session_data);
+ vp = fr_pair_find_by_da(&request->session_state_pairs, attr_tls_session_data);
if (!vp) {
RWDEBUG("No cached session found");
return NULL;
/*
* Ensure that the session data can't be used by anyone else.
*/
- fr_pair_delete_by_da(&request->state_pairs, attr_tls_session_data);
+ fr_pair_delete_by_da(&request->session_state_pairs, attr_tls_session_data);
return sess;
}
continue;
}
- MEM(vp = fr_pair_afrom_da(request, da));
+ MEM(vp = fr_pair_afrom_da(request->request_ctx, da));
if (fr_pair_value_from_str(vp, value, -1, '\0', true) < 0) {
RPWDEBUG3("Skipping: %s += '%s'", attribute, value);
talloc_free(vp);
RDEBUG2("Cipher suite: %s", cipher_desc_clean);
RDEBUG2("Adding TLS session information to request");
- vp = fr_pair_afrom_da(request->state_ctx, attr_tls_session_cipher_suite);
+ vp = fr_pair_afrom_da(request->session_state_ctx, attr_tls_session_cipher_suite);
if (vp) {
fr_pair_value_strdup(vp, SSL_CIPHER_get_name(cipher));
- fr_pair_add(&request->state_pairs, vp);
+ fr_pair_add(&request->session_state_pairs, vp);
RINDENT();
RDEBUG2("&session-state.%pP", vp);
REXDENT();
version = tls_version_str[session->info.version];
}
- vp = fr_pair_afrom_da(request->state_ctx, attr_tls_session_version);
+ vp = fr_pair_afrom_da(request->session_state_ctx, attr_tls_session_version);
if (vp) {
fr_pair_value_strdup(vp, version);
- fr_pair_add(&request->state_pairs, vp);
+ fr_pair_add(&request->session_state_pairs, vp);
RINDENT();
RDEBUG2("&session-state.TLS-Session-Version := \"%s\"", version);
REXDENT();
return NULL;
}
- request = request_alloc(session);
+ request = request_alloc(session, NULL);
fr_tls_session_request_bind(request, session->ssl);
* cert_vps have a different talloc parent, so we
* can't just reference them.
*/
- MEM(fr_pair_list_copy(request->state_ctx, &request->state_pairs, &cert_vps) >= 0);
+ MEM(fr_pair_list_copy(request->session_state_ctx, &request->session_state_pairs, &cert_vps) >= 0);
fr_pair_list_free(&cert_vps);
}
}
{
request_t *child;
- if (!detachable) {
- child = request_alloc_fake(parent, namespace);
- } else {
- child = request_alloc_detachable(parent, namespace);
- }
+ child = request_alloc(detachable ? NULL : parent,
+ (&(request_init_args_t){
+ .parent = parent,
+ .namespace = namespace,
+ .detachable = detachable
+ }));
if (!child) return NULL;
/*
*/
child->async->process = unlang_io_process_interpret;
+ REQUEST_VERIFY(child);
+
return child;
}
*/
static unlang_action_t unlang_parallel_process(rlm_rcode_t *p_result, request_t *request)
{
- unlang_stack_t *stack = request->stack;
- unlang_stack_frame_t *frame = &stack->frame[stack->depth];
- unlang_parallel_state_t *state = talloc_get_type_abort(frame->state, unlang_parallel_state_t);
+ unlang_stack_t *stack = request->stack;
+ unlang_stack_frame_t *frame = &stack->frame[stack->depth];
+ unlang_parallel_state_t *state = talloc_get_type_abort(frame->state, unlang_parallel_state_t);
- int i, priority;
- rlm_rcode_t result;
- unlang_parallel_child_state_t child_state = CHILD_DONE; /* hope that we're done */
+ int i, priority;
+ rlm_rcode_t result;
+ unlang_parallel_child_state_t child_state = CHILD_DONE; /* hope that we're done */
request_t *child;
/*
* contains state information for
* the parent.
*/
- if ((fr_pair_list_copy(child->packet,
+ if ((fr_pair_list_copy(child->request_ctx,
&child->request_pairs,
&request->request_pairs) < 0) ||
- (fr_pair_list_copy(child->reply,
+ (fr_pair_list_copy(child->reply_ctx,
&child->reply_pairs,
&request->reply_pairs) < 0) ||
- (fr_pair_list_copy(child,
+ (fr_pair_list_copy(child->control_ctx,
&child->control_pairs,
&request->control_pairs) < 0)) {
REDEBUG("failed copying lists to clone");
{ NULL }
};
-static fr_dict_attr_t const *attr_request_lifetime;
+static fr_dict_attr_t const *request_attr_request_lifetime;
extern fr_dict_attr_autoload_t subrequest_dict_attr[];
fr_dict_attr_autoload_t subrequest_dict_attr[] = {
- { .out = &attr_request_lifetime, .name = "Request-Lifetime", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
+ { .out = &request_attr_request_lifetime, .name = "Request-Lifetime", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
{ NULL }
};
state->session.unique_ptr,
state->session.unique_int);
+ REQUEST_VERIFY(child);
+
RDEBUG2("Creating subrequest (%s)", child->name);
log_request_pair_list(L_DBG_LVL_1, request, NULL, &child->request_pairs, NULL);
/*
* Set the packet type.
*/
- MEM(vp = fr_pair_afrom_da(child->packet, gext->attr_packet_type));
+ MEM(vp = fr_pair_afrom_da(child->request_ctx, gext->attr_packet_type));
if (gext->type_enum) {
child->packet->code = vp->vp_uint32 = gext->type_enum->value->vb_uint32;
if (gext->src) {
if (tmpl_is_list(gext->src)) {
- if (tmpl_copy_pairs(child->packet, &child->request_pairs, request, gext->src) < -1) {
+ if (tmpl_copy_pairs(child->request_ctx, &child->request_pairs, request, gext->src) < -1) {
RPEDEBUG("Failed copying source attributes into subrequest");
goto fail;
}
} else {
- if (tmpl_copy_pair_children(child->packet, &child->request_pairs, request, gext->src) < -1) {
+ if (tmpl_copy_pair_children(child->request_ctx, &child->request_pairs, request, gext->src) < -1) {
RPEDEBUG("Failed copying source attributes into subrequest");
goto fail;
}
/*
* Set Request Lifetime
*/
- vp = fr_pair_find_by_da(&request->control_pairs, attr_request_lifetime);
+ vp = fr_pair_find_by_da(&request->control_pairs, request_attr_request_lifetime);
if (!vp || (vp->vp_uint32 > 0)) {
fr_time_delta_t when = 0;
const fr_event_timer_t **ev_p;
TEST_MSG("Got length : %zu", (ssize_t)_our_got); \
} while(0)
+#define TEST_CHECK_RET(_got, _exp) \
+do { \
+ int _our_got = (_got); \
+ TEST_CHECK(_exp == _our_got); \
+ TEST_MSG("Expected ret : %"PRId64, (int64_t)_exp); \
+ TEST_MSG("Got ret : %"PRId64, (int64_t)_our_got); \
+} while(0)
#define TEST_CHECK_SLEN(_got, _exp) \
do { \
ssize_t _our_got = (_got); \
fr_pair_t *vp;
vp = talloc_zero(ctx, fr_pair_t);
- if (!vp) {
+ if (unlikely(!vp)) {
fr_strerror_const("Out of memory");
return NULL;
}
return vp;
}
+/** A special allocation function which disables child autofree
+ *
+ * This is intended to allocate root attributes for requests.
+ * These roots are special in that they do not necessarily own
+ * the child attributes and _MUST NOT_ free them when they
+ * themselves are freed.
+ *
+ * @param[in] ctx to allocate the pair root in.
+ * @param[in] da The root attribute.
+ * @return
+ * - A new root pair on success.
+ * - NULL on failure.
+ * @hidecallergraph
+ */
+fr_pair_t *fr_pair_root_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
+{
+ fr_pair_t *vp;
+
+ vp = talloc_zero(ctx, fr_pair_t);
+ if (unlikely(!vp)) {
+ fr_strerror_const("Out of memory");
+ return NULL;
+ }
+
+ vp->op = T_OP_EQ;
+ vp->type = VT_NONE;
+
+ if (unlikely(da->flags.is_unknown)) {
+ fr_strerror_const("Root attribute cannot be unknown");
+ return NULL;
+ }
+
+ vp->da = da;
+
+#ifndef NDEBUG
+ switch (da->type) {
+ case FR_TYPE_GROUP:
+#endif
+ fr_pair_list_init(&vp->children);
+
+#ifndef NDEBUG
+ break;
+
+ default:
+ fr_strerror_const("Root must be a group type");
+ return NULL;
+ }
+#endif
+
+ return vp;
+}
+
/** Dynamically allocate a new attribute and assign a #fr_dict_attr_t
*
* @note Will duplicate any unknown attributes passed as the da.
fr_pair_t *vp;
vp = fr_pair_alloc_null(ctx);
- if (!vp) {
- fr_strerror_const("Out of memory");
- return NULL;
- }
+ if (!vp) return NULL;
/*
* If we get passed an unknown da, we need to ensure that
* Use the 'da' to initialize more fields.
*/
vp->da = da;
- fr_value_box_init(&vp->data, da->type, da, false);
+
+ switch (da->type) {
+ case FR_TYPE_STRUCTURAL:
+ fr_pair_list_init(&vp->children);
+ break;
+
+ default:
+ fr_value_box_init(&vp->data, da->type, da, false);
+ break;
+ }
return vp;
}
fr_table_str_by_value(fr_value_box_type_table, FR_TYPE_OCTETS, "<INVALID>"),
fr_table_str_by_value(fr_value_box_type_table, vp->data.type, "<INVALID>"));
}
- } else if (vp->da->type != vp->data.type) {
- char data_type_int[10], da_type_int[10];
+ } else {
+ switch (vp->da->type) {
+ case FR_TYPE_VALUE:
+ if (vp->da->type != vp->data.type) {
+ char data_type_int[10], da_type_int[10];
- snprintf(data_type_int, sizeof(data_type_int), "%i", vp->data.type);
- snprintf(da_type_int, sizeof(da_type_int), "%i", vp->da->type);
+ snprintf(data_type_int, sizeof(data_type_int), "%i", vp->data.type);
+ snprintf(da_type_int, sizeof(da_type_int), "%i", vp->da->type);
- fr_fatal_assert_fail("CONSISTENCY CHECK FAILED %s[%u]: fr_pair_t attribute %p \"%s\" "
- "data type (%s) does not match da type (%s)",
- file, line, vp->da, vp->da->name,
- fr_table_str_by_value(fr_value_box_type_table, vp->data.type, data_type_int),
- fr_table_str_by_value(fr_value_box_type_table, vp->da->type, da_type_int));
+ fr_fatal_assert_fail("CONSISTENCY CHECK FAILED %s[%u]: fr_pair_t attribute %p \"%s\" "
+ "data type (%s) does not match da type (%s)",
+ file, line, vp->da, vp->da->name,
+ fr_table_str_by_value(fr_value_box_type_table, vp->data.type, data_type_int),
+ fr_table_str_by_value(fr_value_box_type_table, vp->da->type, da_type_int));
+ }
+ break;
+
+ default:
+ break;
+ }
}
}
# define LIST_VERIFY(_x)
#endif
-#define request_pairs request_list
-#define reply_pairs reply_list
-#define control_pairs control_list
-#define state_pairs state_list
-
/** The type of value a fr_pair_t contains
*
* This is used to add structure to nested fr_pair_ts and specifies what type of node it is (set, list, data).
}
/* Allocation and management */
+fr_pair_list_t *fr_pair_list_alloc(TALLOC_CTX *ctx);
+
fr_pair_t *fr_pair_alloc_null(TALLOC_CTX *ctx);
-fr_pair_list_t *fr_pair_list_alloc(TALLOC_CTX *ctx);
+fr_pair_t *fr_pair_root_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da) CC_HINT(nonnull(2));
-/**
- *
- * @hidecallergraph
- */
fr_pair_t *fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da) CC_HINT(nonnull(2));
fr_pair_t *fr_pair_afrom_child_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr);
*/
request->dict = dict_arp;
- if (fr_arp_decode(request->packet, data, data_len, &request->request_pairs) < 0) {
+ if (fr_arp_decode(request->request_ctx, data, data_len, &request->request_pairs) < 0) {
RPEDEBUG("Failed decoding packet");
return -1;
}
static void bfd_request(bfd_state_t *session, request_t *request, fr_radius_packet_t *packet)
{
- memset(request, 0, sizeof(*request));
- fr_pair_list_init(&request->request_pairs);
- fr_pair_list_init(&request->reply_pairs);
- fr_pair_list_init(&request->control_pairs);
- fr_pair_list_init(&request->state_pairs);
-
memset(packet, 0, sizeof(*packet));
request->packet = packet;
static void bfd_trigger(bfd_state_t *session)
{
- fr_radius_packet_t packet;
- request_t request;
- char buffer[256];
+ fr_radius_packet_t packet;
+ request_t *request = request_local_alloc(session, NULL);
+ char buffer[256];
snprintf(buffer, sizeof(buffer), "server.bfd.%s",
bfd_state[session->session_state]);
- bfd_request(session, &request, &packet);
+ bfd_request(session, request, &packet);
- trigger_exec(&request, NULL, buffer, false, NULL);
+ trigger_exec(request, NULL, buffer, false, NULL);
}
request_t *request;
fr_radius_packet_t *packet, *reply;
- request = request_alloc(session);
+ request = request_alloc(session, NULL);
packet = fr_radius_packet_alloc(request, 0);
reply = fr_radius_packet_alloc(request, 0);
timestamp = atoi((char const *) p);
- vp = fr_pair_afrom_da(request->packet, attr_packet_original_timestamp);
+ vp = fr_pair_afrom_da(request->request_ctx, attr_packet_original_timestamp);
if (vp) {
vp->vp_date = ((fr_time_t) timestamp) * NSEC;
vp->type = VT_DATA;
* functions walking over the list.
*/
vp = NULL;
- if ((fr_pair_list_afrom_str(request->packet, request->dict, (char const *) p, &vp) > 0) && vp) {
+ if ((fr_pair_list_afrom_str(request->request_ctx, request->dict, (char const *) p, &vp) > 0) && vp) {
fr_cursor_append(&cursor, vp);
} else {
RWDEBUG("Ignoring line %d - :%s", lineno, p);
vp;
vp = fr_cursor_next(&cursor)) {
if (vp->da == attr_hop_count) {
- fr_pair_add(&request->reply_pairs, fr_pair_copy(request->reply, vp));
+ fr_pair_add(&request->reply_pairs, fr_pair_copy(request->reply_ctx, vp));
continue;
}
if (vp->da == attr_relay_link_address) {
- fr_pair_add(&request->reply_pairs, fr_pair_copy(request->reply, vp));
+ fr_pair_add(&request->reply_pairs, fr_pair_copy(request->reply_ctx, vp));
continue;
}
if (vp->da == attr_relay_peer_address) {
- fr_pair_add(&request->reply_pairs, fr_pair_copy(request->reply, vp));
+ fr_pair_add(&request->reply_pairs, fr_pair_copy(request->reply_ctx, vp));
continue;
}
if (vp->da == attr_interface_id) {
- fr_pair_add(&request->reply_pairs, fr_pair_copy(request->reply, vp));
+ fr_pair_add(&request->reply_pairs, fr_pair_copy(request->reply_ctx, vp));
continue;
}
}
break;
default:
- fr_pair_list_copy_by_da(request->reply, &request->reply_pairs, &request->request_pairs, attr_transaction_id, 1);
- fr_pair_list_copy_by_ancestor(request->reply, &request->reply_pairs, &request->request_pairs, attr_client_id, 0);
+ fr_pair_list_copy_by_da(request->reply_ctx, &request->reply_pairs, &request->request_pairs, attr_transaction_id, 1);
+ fr_pair_list_copy_by_ancestor(request->reply_ctx, &request->reply_pairs, &request->request_pairs, attr_client_id, 0);
break;
}
}
* Add reply->packet-type in case we're
* being called via the `call {}` keyword.
*/
- MEM(fr_pair_update_by_da(request->reply, &reply_packet_type,
+ MEM(fr_pair_update_by_da(request->reply_ctx, &reply_packet_type,
&request->reply_pairs, attr_packet_type) >= 0);
reply_packet_type->vp_uint32 = request->reply->code;
* transport, via a call to fr_radius_ok().
*/
fr_cursor_init(&cursor, &request->request_pairs);
- if (fr_radius_decode(request->packet, request->packet->data, request->packet->data_len,
+ if (fr_radius_decode(request->request_ctx, request->packet->data, request->packet->data_len,
NULL, client->secret, talloc_array_length(client->secret) - 1,
&cursor) < 0) {
RPEDEBUG("Failed decoding packet");
* transport, via a call to ???
*/
fr_cursor_init(&cursor, &request->request_pairs);
- if (fr_tacacs_decode(request->packet, request->packet->data, request->packet->data_len,
+ if (fr_tacacs_decode(request->request_ctx, request->packet->data, request->packet->data_len,
NULL, client->secret, talloc_array_length(client->secret) - 1,
&cursor) < 0) {
RPEDEBUG("Failed decoding packet");
memcpy(buffer, &request->async->listen, sizeof(request->async->listen));
memcpy(buffer + sizeof(request->async->listen), &pkt->session_id, sizeof(pkt->session_id));
- vp = fr_pair_afrom_da(request->packet, attr_tacacs_state);
+ vp = fr_pair_afrom_da(request->request_ctx, attr_tacacs_state);
if (vp) {
fr_pair_value_memdup(vp, buffer, sizeof(buffer), false);
fr_pair_add(&request->request_pairs, vp);
memcpy(buffer, &request->async->listen, sizeof(request->async->listen));
memcpy(buffer + sizeof(request->async->listen), &pkt->session_id, sizeof(pkt->session_id));
- vp = fr_pair_afrom_da(request->packet, attr_tacacs_state);
+ vp = fr_pair_afrom_da(request->request_ctx, attr_tacacs_state);
if (vp) {
fr_pair_value_memdup(vp, buffer, sizeof(buffer), false);
fr_pair_add(&request->request_pairs, vp);
* transport, via a call to fr_vmps_ok().
*/
fr_cursor_init(&cursor, &request->request_pairs);
- if (fr_vmps_decode(packet, packet->data, packet->data_len, &cursor, &packet->code) < 0) {
+ if (fr_vmps_decode(request->request_ctx, packet->data, packet->data_len, &cursor, &packet->code) < 0) {
RPEDEBUG("Failed decoding packet");
return -1;
}
if (!vp) {
RDEBUG2("Creating &%s from request authenticator", attr_chap_challenge->name);
- MEM(vp = fr_pair_afrom_da(request->packet, attr_chap_challenge));
+ MEM(vp = fr_pair_afrom_da(request->request_ctx, attr_chap_challenge));
fr_pair_value_memdup(vp, request->packet->vector, sizeof(request->packet->vector), true);
fr_pair_add(&request->request_pairs, vp);
}
* Loop over all the options data
*/
while (p < end) {
- len = fr_dhcpv4_decode_option(request->packet, &options_cursor, dict_dhcpv4,
+ len = fr_dhcpv4_decode_option(request->request_ctx, &options_cursor, dict_dhcpv4,
p, end - p, NULL);
if (len <= 0) {
RPERROR("DHCP option decoding failed");
decoded++;
}
- fr_pair_list_move(&(request->request_pairs), &head);
+ fr_pair_list_move(&request->request_pairs, &head);
/* Free any unmoved pairs */
fr_pair_list_free(&head);
RETURN_MODULE_FAIL;
}
- if (fr_pair_list_copy(eap_session->subrequest->packet,
+ if (fr_pair_list_copy(eap_session->subrequest->request_ctx,
&eap_session->subrequest->request_pairs,
&request->request_pairs) < 0) goto list_copy_fail;
}
*/
vp = fr_pair_find_by_da(&request->reply_pairs, attr_user_name);
if (!vp) {
- vp = fr_pair_copy(request->reply, username);
+ vp = fr_pair_copy(request->reply_ctx, username);
fr_pair_add(&request->reply_pairs, vp);
}
/*
* Allocate a fake request_t structure.
*/
- fake = request_alloc_fake(request, NULL);
+ fake = request_alloc(request, &(request_init_args_t){ .parent = request });
fr_assert(!fake->request_pairs);
t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);
* Add the tunneled attributes to the fake request.
*/
- MEM(fake->request_pairs = vp = fr_pair_afrom_da(fake->packet, attr_eap_message));
+ MEM(fake->request_pairs = vp = fr_pair_afrom_da(fake->request_ctx, attr_eap_message));
fr_pair_value_memdup(fake->request_pairs, tlv_eap_payload->vp_octets, tlv_eap_payload->vp_length, false);
RDEBUG2("Got tunneled request");
/*
* Tell the request that it's a fake one.
*/
- MEM(fr_pair_add_by_da(fake->packet, &vp, &fake->request_pairs, attr_freeradius_proxied_to) >= 0);
+ MEM(fr_pair_add_by_da(fake->request_ctx, &vp, &fake->request_pairs, attr_freeradius_proxied_to) >= 0);
fr_pair_value_from_str(vp, "127.0.0.1", sizeof("127.0.0.1"), '\0', false);
/*
} /* else there WAS a t->username */
if (t->username) {
- vp = fr_pair_copy(fake->packet, t->username);
+ vp = fr_pair_copy(fake->request_ctx, t->username);
fr_pair_add(&fake->request_pairs, vp);
}
/*
* Tell the original request that it's going to be proxied.
*/
- fr_pair_list_copy_by_da(request, &request->control_pairs,
- &fake->control, attr_proxy_to_realm, 0);
+ fr_pair_list_copy_by_da(request->control_ctx, &request->control_pairs,
+ &fake->control_pairs, attr_proxy_to_realm, 0);
/*
* Seed the proxy packet with the tunneled request.
/*
* FIXME: Actually proxy stuff
*/
- request->proxy = request_alloc_fake(request, NULL);
+ request->proxy = request_alloc(request, &(request_init_args_t){ .parent = request });
request->proxy->packet = talloc_steal(request->proxy, fake->packet);
memset(&request->proxy->packet->src_ipaddr, 0,
if (data->mppe_keys) {
RDEBUG2("Adding stored attributes to parent");
log_request_pair_list(L_DBG_LVL_2, request, NULL, &data->mppe_keys, "&parent.reply.");
- MEM(fr_pair_list_copy(parent->reply, &parent->reply_pairs, &data->mppe_keys) >= 0);
+ MEM(fr_pair_list_copy(parent->reply_ctx, &parent->reply_pairs, &data->mppe_keys) >= 0);
} else {
RDEBUG2("No stored attributes to copy to parent");
}
*/
request->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
#endif
- MEM(fr_pair_list_copy(parent->reply, &parent->reply_pairs, &data->reply) >= 0);
+ MEM(fr_pair_list_copy(parent->reply_ctx, &parent->reply_pairs, &data->reply) >= 0);
RETURN_MODULE_OK;
}
REDEBUG("Sent SUCCESS expecting SUCCESS (or ACK) but got %d", ccode);
return 1;
}
-static void eap_peap_soh_verify(request_t *request, fr_radius_packet_t *packet,
- uint8_t const *data, unsigned int data_len) {
+static void eap_peap_soh_verify(request_t *request, uint8_t const *data, unsigned int data_len) {
fr_pair_t *vp;
uint8_t eap_method_base;
uint32_t eap_method;
int rv;
- MEM(vp = fr_pair_afrom_da(packet, attr_soh_supported));
+ MEM(vp = fr_pair_afrom_da(request->request_ctx, attr_soh_supported));
vp->vp_bool = false;
fr_pair_add(&request->request_pairs, vp);
/*
* Convert a pseudo-EAP packet to a list of fr_pair_t's.
*/
-static fr_pair_t *eap_peap_inner_to_pairs(UNUSED request_t *request, fr_radius_packet_t *packet,
- eap_round_t *eap_round,
- uint8_t const *data, size_t data_len)
+static void eap_peap_inner_to_pairs(TALLOC_CTX *ctx, fr_pair_list_t *pairs,
+ eap_round_t *eap_round,
+ uint8_t const *data, size_t data_len)
{
size_t total;
uint8_t *p;
fr_pair_t *vp = NULL;
- fr_pair_list_t head;
fr_cursor_t cursor;
- fr_pair_list_init(&head);
- if (data_len > 65535) return NULL; /* paranoia */
+ if (data_len > 65535) return; /* paranoia */
- MEM(vp = fr_pair_afrom_da(packet, attr_eap_message));
+ MEM(vp = fr_pair_afrom_da(ctx, attr_eap_message));
total = data_len;
if (total > 249) total = 249;
p[3] = (data_len + EAP_HEADER_LEN) & 0xff;
memcpy(p + EAP_HEADER_LEN, data, total);
- fr_cursor_init(&cursor, &head);
+ fr_cursor_init(&cursor, pairs);
fr_cursor_append(&cursor, vp);
while (total < data_len) {
- MEM(vp = fr_pair_afrom_da(packet, attr_eap_message));
+ MEM(vp = fr_pair_afrom_da(ctx, attr_eap_message));
fr_pair_value_memdup(vp, data + total, (data_len - total), false);
total += vp->vp_length;
fr_cursor_append(&cursor, vp);
}
-
- return head;
}
break;
case PEAP_STATUS_WAIT_FOR_SOH_RESPONSE:
- fake = request_alloc_fake(request, NULL);
+ fake = request_alloc(request, &(request_init_args_t){ .parent = request });
fr_assert(!fake->request_pairs);
- eap_peap_soh_verify(fake, fake->packet, data, data_len);
+ eap_peap_soh_verify(fake, data, data_len);
setup_fake_request(request, fake, t);
if (t->soh_virtual_server) fake->server_cs = virtual_server_find(t->soh_virtual_server);
goto finish;
}
- fake = request_alloc_fake(request, NULL);
+ fake = request_alloc(request, &(request_init_args_t){ .parent = request });
fr_assert(!fake->request_pairs);
switch (t->status) {
len = t->username->vp_length + EAP_HEADER_LEN + 1;
t->status = PEAP_STATUS_PHASE2;
- MEM(vp = fr_pair_afrom_da(fake->packet, attr_eap_message));
+ MEM(vp = fr_pair_afrom_da(fake->request_ctx, attr_eap_message));
MEM(fr_pair_value_mem_alloc(vp, &q, len, false) == 0);
q[0] = FR_EAP_CODE_RESPONSE;
q[1] = eap_round->response->id;
break;
case PEAP_STATUS_PHASE2:
- fake->request_pairs = eap_peap_inner_to_pairs(request, fake->packet,
- eap_round, data, data_len);
+ eap_peap_inner_to_pairs(fake->request_ctx, &fake->request_pairs,
+ eap_round, data, data_len);
if (!fake->request_pairs) {
talloc_free(fake);
RDEBUG2("Unable to convert tunneled EAP packet to internal server data structures");
REDEBUG("Unknown RADIUS packet type %d: rejecting tunneled user", fake->reply->code);
rcode = RLM_MODULE_REJECT;
} else {
- rcode = process_reply(eap_session, tls_session, request, fake->reply, &fake->reply_list);
+ rcode = process_reply(eap_session, tls_session, request, fake->reply, &fake->reply_pairs);
}
finish:
/*
* Tell the request that it's a fake one.
*/
- MEM(fr_pair_add_by_da(fake->packet, &vp, &fake->request_pairs, attr_freeradius_proxied_to) >= 0);
+ MEM(fr_pair_add_by_da(fake->request_ctx, &vp, &fake->request_pairs, attr_freeradius_proxied_to) >= 0);
fr_pair_value_from_str(vp, "127.0.0.1", sizeof("127.0.0.1"), '\0', false);
if (t->username) {
- vp = fr_pair_copy(fake->packet, t->username);
+ vp = fr_pair_copy(fake->request_ctx, t->username);
fr_pair_add(&fake->request_pairs, vp);
RDEBUG2("Setting &request.User-Name from tunneled (inner) identity \"%s\"",
vp->vp_strvalue);
* Add the tunneled attributes to the request request.
*/
fr_cursor_init(&cursor, &request->request_pairs);
- if (eap_ttls_decode_pair(request->packet, &cursor, fr_dict_root(fr_dict_internal()),
+ if (eap_ttls_decode_pair(request->request_ctx, &cursor, fr_dict_root(fr_dict_internal()),
data, data_len, tls_session->ssl) < 0) {
RPEDEBUG("Decoding TTLS TLVs failed");
code = FR_CODE_ACCESS_REJECT;
} /* else there WAS a t->username */
if (t->username) {
- vp = fr_pair_copy(request->packet, t->username);
+ vp = fr_pair_copy(request->request_ctx, t->username);
fr_pair_add(&request->request_pairs, vp);
}
} /* else the request ALREADY had a User-Name */
if (req->response) {
RDEBUG2("sending chbind response");
fr_pair_add(&request->reply_pairs,
- eap_chbind_packet2vp(request->reply, req->response));
+ eap_chbind_packet2vp(request->reply_ctx, req->response));
} else {
RDEBUG2("no chbind response");
}
for (map = fr_cursor_init(&cursor, &pl->check);
map;
map = fr_cursor_next(&cursor)) {
- if (map_to_vp(request, &vp, request, map, NULL) < 0) {
+ if (map_to_vp(request->control_ctx, &vp, request, map, NULL) < 0) {
fr_pair_list_free(&list);
RPWARN("Failed parsing map for check item, skipping entry");
break;
map = fr_cursor_next(&cursor)) {
if (map->op == T_OP_CMP_FALSE) continue;
- if (map_to_vp(request->reply, &vp, request, map, NULL) < 0) {
+ if (map_to_vp(request->reply_ctx, &vp, request, map, NULL) < 0) {
RPWARN("Failed parsing map for reply item %s, skipping it", map->rhs->name);
break;
}
if (info->cmd->type != ISC_FIXED_ADDRESS) continue;
- MEM(vp = fr_pair_afrom_da(request->reply_pairs, attr_your_ip_address));
+ MEM(vp = fr_pair_afrom_da(request->reply_ctx, attr_your_ip_address));
ret = fr_value_box_copy(vp, &(vp->data), info->argv[0]);
if (ret < 0) return ret;
while (vp) {
fr_pair_t *next, *copy;
- copy = fr_pair_copy(request->reply, vp);
+ copy = fr_pair_copy(request->reply_ctx, vp);
if (!copy) return -1;
fr_cursor_append(&reply_cursor, copy);
* - 0 on success.
* - -1 on failure.
*/
-static int fr_lua_unmarshall(fr_pair_t **out,
+static int fr_lua_unmarshall(TALLOC_CTX *ctx, fr_pair_t **out,
UNUSED rlm_lua_t const *inst, request_t *request, lua_State *L, fr_dict_attr_t const *da)
{
fr_pair_t *vp;
- MEM(vp = fr_pair_afrom_da(request, da));
+ MEM(vp = fr_pair_afrom_da(ctx, da));
switch (lua_type(L, -1)) {
case LUA_TNUMBER:
{
return 0;
}
- if (fr_lua_unmarshall(&new, inst, request, L, da) < 0) return -1;
+ if (fr_lua_unmarshall(request->request_ctx, &new, inst, request, L, da) < 0) return -1;
/*
* If there was already a VP at that index we replace it
mruby_set_vps(request, mrb, mruby_request, "@request", &request->request_pairs);
mruby_set_vps(request, mrb, mruby_request, "@reply", &request->reply_pairs);
mruby_set_vps(request, mrb, mruby_request, "@control", &request->control_pairs);
- mruby_set_vps(request, mrb, mruby_request, "@session_state", &request->state_pairs);
+ mruby_set_vps(request, mrb, mruby_request, "@session_state", &request->session_state_pairs);
DIAG_OFF(class-varargs)
mruby_result = mrb_funcall(mrb, mrb_obj_value(inst->mruby_module), function_name, 1, mruby_request);
RETURN_MODULE_FAIL;
}
- add_vp_tuple(request->reply, request, &request->reply_pairs, mrb, mrb_ary_entry(mruby_result, 1), function_name);
- add_vp_tuple(request, request, &request->control_pairs, mrb, mrb_ary_entry(mruby_result, 2), function_name);
+ add_vp_tuple(request->reply_ctx, request, &request->reply_pairs, mrb, mrb_ary_entry(mruby_result, 1), function_name);
+ add_vp_tuple(request->control_ctx, request, &request->control_pairs, mrb, mrb_ary_entry(mruby_result, 2), function_name);
RETURN_MODULE_RCODE((rlm_rcode_t)mrb_int(mrb, mrb_ary_entry(mruby_result, 0)));
default:
int ret;
fr_pair_t *nt_password;
- MEM(nt_password = fr_pair_afrom_da(request, attr_nt_password));
+ MEM(nt_password = fr_pair_afrom_da(request->request_ctx, attr_nt_password));
MEM(fr_pair_value_mem_alloc(nt_password, &p, NT_DIGEST_LENGTH, false) == 0);
ret = mschap_nt_password_hash(p, password->vp_strvalue);
if (!pw) continue;
do {
- result_add(request, inst, request, &request->control_pairs, pw, 0, "config");
- result_add(request->reply, inst, request, &request->reply_pairs, pw, 1, "reply_items");
- result_add(request->packet, inst, request, &request->request_pairs, pw, 2, "request_items");
+ result_add(request->control_ctx, inst, request, &request->control_pairs, pw, 0, "config");
+ result_add(request->reply_ctx, inst, request, &request->reply_pairs, pw, 1, "reply_items");
+ result_add(request->request_ctx, inst, request, &request->request_pairs, pw, 2, "request_items");
} while ((pw = get_next(buffer, inst->ht, &last_found)));
found++;
rad_request_hv = get_hv("RAD_REQUEST", 1);
rad_state_hv = get_hv("RAD_STATE", 1);
- perl_store_vps(request->packet, request, &request->request_pairs, rad_request_hv, "RAD_REQUEST", "request");
- perl_store_vps(request->reply, request, &request->reply_pairs, rad_reply_hv, "RAD_REPLY", "reply");
- perl_store_vps(request, request, &request->control_pairs, rad_config_hv, "RAD_CONFIG", "control");
- perl_store_vps(request->state_ctx, request, &request->state_pairs, rad_state_hv, "RAD_STATE", "session-state");
+ perl_store_vps(request->request_ctx, request, &request->request_pairs, rad_request_hv, "RAD_REQUEST", "request");
+ perl_store_vps(request->reply_ctx, request, &request->reply_pairs, rad_reply_hv, "RAD_REPLY", "reply");
+ perl_store_vps(request->control_ctx, request, &request->control_pairs, rad_config_hv, "RAD_CONFIG", "control");
+ perl_store_vps(request->session_state_ctx, request, &request->session_state_pairs, rad_state_hv, "RAD_STATE", "session-state");
/*
* Store pointer to request structure globally so radiusd::xlat works
LEAVE;
vp = NULL;
- if ((get_hv_content(request->packet, request, rad_request_hv, &vp, "RAD_REQUEST", "request")) == 0) {
+ if ((get_hv_content(request->request_ctx, request, rad_request_hv, &vp, "RAD_REQUEST", "request")) == 0) {
fr_pair_list_free(&request->request_pairs);
request->request_pairs = vp;
vp = NULL;
}
- if ((get_hv_content(request->reply, request, rad_reply_hv, &vp, "RAD_REPLY", "reply")) == 0) {
+ if ((get_hv_content(request->reply_ctx, request, rad_reply_hv, &vp, "RAD_REPLY", "reply")) == 0) {
fr_pair_list_free(&request->reply_pairs);
request->reply_pairs = vp;
vp = NULL;
}
- if ((get_hv_content(request, request, rad_config_hv, &vp, "RAD_CONFIG", "control")) == 0) {
+ if ((get_hv_content(request->control_ctx, request, rad_config_hv, &vp, "RAD_CONFIG", "control")) == 0) {
fr_pair_list_free(&request->control_pairs);
request->control_pairs = vp;
vp = NULL;
}
- if ((get_hv_content(request->state_ctx, request, rad_state_hv, &vp, "RAD_STATE", "session-state")) == 0) {
- fr_pair_list_free(&request->state_pairs);
- request->state_pairs = vp;
+ if ((get_hv_content(request->session_state_ctx, request, rad_state_hv, &vp, "RAD_STATE", "session-state")) == 0) {
+ fr_pair_list_free(&request->session_state_pairs);
+ request->session_state_pairs = vp;
vp = NULL;
}
}
fr_table_str_by_value(fr_tokens_table, op, "="), s2);
}
- radius_pairmove(current, vps, &vp, false);
+ radius_pairmove(request, vps, &vp, false);
}
}
/* Now have the return value */
rcode = PyLong_AsLong(p_tuple_int);
/* Reply item tuple */
- mod_vptuple(request->reply, inst, request, &request->reply_pairs,
+ mod_vptuple(request->reply_ctx, inst, request, &request->reply_pairs,
PyTuple_GET_ITEM(p_ret, 1), funcname, "reply");
/* Config item tuple */
- mod_vptuple(request, inst, request, &request->control_pairs,
+ mod_vptuple(request->control_ctx, inst, request, &request->control_pairs,
PyTuple_GET_ITEM(p_ret, 2), funcname, "config");
} else if (PyNumber_Check(p_ret)) {
* head before the module destructor
* runs.
*/
- request = request_local_alloc(u);
+ request = request_local_alloc(u, NULL);
request->async = talloc_zero(request, fr_async_t);
talloc_const_free(request->name);
request->name = talloc_strdup(request, h->module_name);
/*
* Validate and decode the incoming packet
*/
- reason = decode(request->reply, &reply, &code, h, request, u, rr->vector, h->buffer, (size_t)slen);
+ reason = decode(request->reply_ctx, &reply, &code, h, request, u, rr->vector, h->buffer, (size_t)slen);
if (reason != DECODE_FAIL_NONE) {
RWDEBUG("Ignoring invalid response");
continue;
vp = fr_pair_find_by_da(&request->reply_pairs, attr_packet_type);
if (!vp) {
- MEM(vp = fr_pair_afrom_da(request->reply, attr_packet_type));
+ MEM(vp = fr_pair_afrom_da(request->reply_ctx, attr_packet_type));
vp->vp_uint32 = FR_CODE_ACCESS_CHALLENGE;
fr_pair_add(&request->reply_pairs, vp);
}
fr_pair_delete_by_da(&reply, attr_message_authenticator);
- MEM(vp = fr_pair_afrom_da(request->reply, attr_message_authenticator));
+ MEM(vp = fr_pair_afrom_da(request->reply_ctx, attr_message_authenticator));
(void) fr_pair_value_memdup(vp, (uint8_t const *) "", 1, false);
fr_pair_add(&request->reply_pairs, vp);
}
unsigned int pipelined = 0;
- request = request_alloc(inst);
+ request = request_alloc(inst, NULL);
while (more) {
fr_ipaddr_t acked = ipaddr; /* Record our progress */
size_t reply_cnt = 0;
request_t *request;
uint8_t **result;
- request = request_alloc(inst);
+ request = request_alloc(inst, NULL);
IPPOOL_BUILD_KEY(key, key_p, "*}:pool", 1);
#define STATS_COMMANDS_TOTAL 8
- request = request_alloc(inst);
+ request = request_alloc(inst, NULL);
IPPOOL_BUILD_KEY(key, key_p, key_prefix, key_prefix_len);
RDEBUG2("SIM auth vector %i", i);
RINDENT();
- MEM(vp = fr_pair_afrom_da(request, attr_eap_aka_sim_rand));
+ MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_rand));
MEM(fr_pair_value_memdup_buffer(vp, vec->sim.rand, true) == 0);
TALLOC_FREE(vec->sim.rand);
RDEBUG2("&control.%pP", vp);
fr_cursor_append(&cursor, vp);
- MEM(vp = fr_pair_afrom_da(request, attr_eap_aka_sim_sres));
+ MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_sres));
MEM(fr_pair_value_memdup_buffer(vp, vec->sim.sres, true) == 0);
TALLOC_FREE(vec->sim.sres);
RDEBUG2("&control.%pP", vp);
fr_cursor_append(&cursor, vp);
- MEM(vp = fr_pair_afrom_da(request, attr_eap_aka_sim_kc));
+ MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_kc));
MEM(fr_pair_value_memdup_buffer(vp, vec->sim.kc, true) == 0);
TALLOC_FREE(vec->sim.kc);
RDEBUG2("&control.%pP", vp);
RDEBUG2("UMTS auth vector %i", i);
RINDENT();
- MEM(vp = fr_pair_afrom_da(request, attr_eap_aka_sim_rand));
+ MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_rand));
MEM(fr_pair_value_memdup_buffer(vp, vec->umts.rand, true) == 0);
TALLOC_FREE(vec->umts.rand);
RDEBUG2("&control.%pP", vp);
fr_cursor_append(&cursor, vp);
- MEM(vp = fr_pair_afrom_da(request, attr_eap_aka_sim_xres));
+ MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_xres));
MEM(fr_pair_value_memdup_buffer(vp, vec->umts.xres, true) == 0);
TALLOC_FREE(vec->umts.xres);
RDEBUG2("&control.%pP", vp);
fr_cursor_append(&cursor, vp);
- MEM(vp = fr_pair_afrom_da(request, attr_eap_aka_sim_ck));
+ MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_ck));
MEM(fr_pair_value_memdup_buffer(vp, vec->umts.ck, true) == 0);
TALLOC_FREE(vec->umts.ck);
RDEBUG2("&control.%pP", vp);
fr_cursor_append(&cursor, vp);
- MEM(vp = fr_pair_afrom_da(request, attr_eap_aka_sim_ik));
+ MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_ik));
MEM(fr_pair_value_memdup_buffer(vp, vec->umts.ik, true) == 0);
TALLOC_FREE(vec->umts.ik);
RDEBUG2("&control.%pP", vp);
fr_cursor_append(&cursor, vp);
- MEM(vp = fr_pair_afrom_da(request, attr_eap_aka_sim_autn));
+ MEM(vp = fr_pair_afrom_da(request->control_ctx, attr_eap_aka_sim_autn));
MEM(fr_pair_value_memdup_buffer(vp, vec->umts.authn, true) == 0);
TALLOC_FREE(vec->umts.authn);
RDEBUG2("&control.%pP", vp);
RDEBUG2("SoH adding NAP marker to DHCP reply");
/* client probe; send "NAP" in the reply */
- MEM(vp = fr_pair_afrom_da(request->reply, attr_dhcp_vendor));
+ MEM(vp = fr_pair_afrom_da(request->reply_ctx, attr_dhcp_vendor));
MEM(fr_pair_value_mem_alloc(vp, &p, 5, false) == 0);
p[0] = 220;
p[1] = 3;
}
fr_cursor_init(&cursor, &check_tmp);
- rows = sql_getvpdata(request, inst, request, handle, &cursor, expanded);
+ rows = sql_getvpdata(request->control_ctx, inst, request, handle, &cursor, expanded);
TALLOC_FREE(expanded);
if (rows < 0) {
REDEBUG("Error retrieving check pairs for group %s", entry->name);
}
fr_cursor_init(&cursor, &reply_tmp);
- rows = sql_getvpdata(request->reply, inst, request, handle, &cursor, expanded);
+ rows = sql_getvpdata(request->reply_ctx, inst, request, handle, &cursor, expanded);
TALLOC_FREE(expanded);
if (rows < 0) {
REDEBUG("Error retrieving reply pairs for group %s", entry->name);
}
fr_cursor_init(&cursor, &check_tmp);
- rows = sql_getvpdata(request, inst, request, &handle, &cursor, expanded);
+ rows = sql_getvpdata(request->control_ctx, inst, request, &handle, &cursor, expanded);
TALLOC_FREE(expanded);
if (rows < 0) {
REDEBUG("Failed getting check attributes");
}
fr_cursor_init(&cursor, &reply_tmp);
- rows = sql_getvpdata(request->reply, inst, request, &handle, &cursor, expanded);
+ rows = sql_getvpdata(request->reply_ctx, inst, request, &handle, &cursor, expanded);
TALLOC_FREE(expanded);
if (rows < 0) {
REDEBUG("SQL query error getting reply attributes");
* See if we can create the VP from the returned data. If not,
* error out. If so, add it to the list.
*/
- MEM(vp = fr_pair_afrom_da(request->reply, inst->allocated_address_da));
+ MEM(vp = fr_pair_afrom_da(request->reply_ctx, inst->allocated_address_da));
if (fr_pair_value_from_str(vp, allocation, allocation_len, '\0', true) < 0) {
DO_PART(alloc_commit);
}
if (vp ) {
- vp = fr_pair_copy(request->reply, vp);
+ vp = fr_pair_copy(request->reply_ctx, vp);
if (vp) {
fr_cursor_append(&cursor, vp);
(void) fr_cursor_tail(&cursor);
da = fr_dict_attr_by_name(NULL, fr_dict_root(dict_radius), buffer);
if (!da) continue;
- MEM(vp = fr_pair_afrom_da(request->reply, da));
+ MEM(vp = fr_pair_afrom_da(request->reply_ctx, da));
vp->vp_uint64 = local_stats[i];
fr_cursor_append(&cursor, vp);
goto nothing;
}
- MEM(vp = fr_pair_afrom_da(request, da));
+ MEM(vp = fr_pair_afrom_da(request->request_ctx, da));
/*
* Call the generic routines to get data from the
/**********************************************************************/
typedef struct request_s request_t;
-request_t *request_alloc(UNUSED TALLOC_CTX *ctx);
void request_verify(UNUSED char const *file, UNUSED int line, UNUSED request_t *request);
int talloc_const_free(void const *ptr);
-request_t *request_alloc(UNUSED TALLOC_CTX *ctx)
-{
- return NULL;
-}
-
void request_verify(UNUSED char const *file, UNUSED int line, UNUSED request_t *request)
{
}
/**********************************************************************/
typedef struct request_s request_t;
-request_t *request_alloc(UNUSED TALLOC_CTX *ctx)
+request_t *request_alloc(UNUSED TALLOC_CTX *ctx, UNUSED request_init_args_t const *args)
{
return NULL;
}
/**********************************************************************/
typedef struct request_s request_t;
-request_t *request_alloc(UNUSED TALLOC_CTX *ctx);
+request_t *request_alloc(UNUSED TALLOC_CTX *ctx, UNUSED request_init_args_t const *args);
void request_verify(UNUSED char const *file, UNUSED int line, UNUSED request_t *request);
int talloc_const_free(void const *ptr);
-request_t *request_alloc(UNUSED TALLOC_CTX *ctx)
+request_t *request_alloc(UNUSED TALLOC_CTX *ctx, UNUSED request_init_args_t const *args)
{
return NULL;
}
/**********************************************************************/
typedef struct request_s request_t;
-request_t *request_alloc(UNUSED TALLOC_CTX *ctx);
+request_t *request_alloc(UNUSED TALLOC_CTX *ctx, UNUSED request_init_args_t const *args);
void request_verify(UNUSED char const *file, UNUSED int line, UNUSED request_t *request);
int talloc_const_free(void const *ptr);
-request_t *request_alloc(UNUSED TALLOC_CTX *ctx)
+request_t *request_alloc(UNUSED TALLOC_CTX *ctx, UNUSED request_init_args_t const *args)
{
return NULL;
}
/**********************************************************************/
typedef struct request_s request_t;
-request_t *request_alloc(UNUSED TALLOC_CTX *ctx);
+request_t *request_alloc(UNUSED TALLOC_CTX *ctx, UNUSED request_init_args_t const *args);
void request_verify(UNUSED char const *file, UNUSED int line, UNUSED request_t *request);
int talloc_const_free(void const *ptr);
-request_t *request_alloc(UNUSED TALLOC_CTX *ctx)
+request_t *request_alloc(UNUSED TALLOC_CTX *ctx, UNUSED request_init_args_t const *args)
{
return NULL;
}
/**********************************************************************/
typedef struct request_s request_t;
-request_t *request_alloc(UNUSED TALLOC_CTX *ctx)
+request_t *request_alloc(UNUSED TALLOC_CTX *ctx, UNUSED request_init_args_t const *args)
{
return NULL;
}