25RCSID(
"$Id: a51de1cb81c40f32c34b1ef77531e6467c22fb79 $")
27#include <freeradius-devel/server/request.h>
28#include <freeradius-devel/server/request_data.h>
29#include <freeradius-devel/unlang/interpret.h>
31#include <freeradius-devel/util/debug.h>
32#include <freeradius-devel/util/atexit.h>
63 DEBUG4(
"state-ctx %p freed", state);
75 if (!request->log.dst) {
76 request->log.dst = talloc_zero(request,
log_dst_t);
78 memset(request->log.dst, 0,
sizeof(*request->log.dst));
97 while (request->log.dst) {
98 dst = request->log.dst->next;
100 request->log.dst = dst;
112 last = &request->log.dst;
131 for (dst = request->log.dst; dst != NULL; dst = dst->
next) {
134 if (lvl > request->log.lvl) request->log.lvl = lvl;
148 if (lvl > request->log.lvl) request->log.lvl = lvl;
149 dst->
next = request->log.dst;
151 request->log.dst = dst;
159 memcpy(&(child->log), &(
parent->log),
sizeof(child->log));
160 child->log.indent.unlang = 0;
161 child->log.indent.module = 0;
162 child->log.lvl =
parent->log.lvl;
173 child->log.dst = talloc_zero(child,
log_dst_t);
174 memcpy(child->log.dst,
parent->log.dst,
sizeof(*child->log.dst));
192 child->number =
parent->child_number++;
193 if (!child->proto_dict) {
194 child->proto_dict =
parent->proto_dict;
195 child->local_dict =
parent->proto_dict;
204 child->seq_start = 0;
215 if (!child->packet) {
254 dict =
args->namespace;
261 dict =
args->namespace;
266 fr_assert_fail(
"Detached requests should start as type == REQUEST_TYPE_INTERNAL, "
267 "args->detachable and be detached later");
279 .component =
"<pre-core>",
281 .detachable =
args &&
args->detachable,
308 if (
unlikely(!pair_root))
return -1;
309 request->pair_root = pair_root;
317 if (
args) memcpy(&request->pair_list, &
args->pair_list,
sizeof(request->pair_list));
319#define list_init(_ctx, _list) \
321 vp = fr_pair_afrom_da(_ctx, request_attr_##_list); \
322 if (unlikely(!vp)) { \
323 talloc_free(pair_root); \
324 memset(&request->pair_list, 0, sizeof(request->pair_list)); \
327 fr_pair_append(&pair_root->children, vp); \
328 request->pair_list._list = vp; \
331 if (!request->pair_list.request)
list_init(request->pair_root, request);
332 if (!request->pair_list.reply)
list_init(request->pair_root, reply);
333 if (!request->pair_list.control)
list_init(request->pair_root, control);
334 if (!request->pair_list.local)
list_init(request->pair_root, local);
335 if (!request->pair_list.state) {
351 if (
args->detachable) {
381 "alloced %s:%i: %s still in the timeout sublist",
384 request->name ? request->name :
"(null)");
386 "alloced %s:%i: %s still in the runnable heap ID %i",
389 request->name ? request->name :
"(null)", request->runnable);
391 RDEBUG3(
"Request deinitialising (%p)", request);
396 if (request->session_state_ctx) TALLOC_FREE(request->session_state_ctx);
401 memset(request, 0,
sizeof(*request));
404 request->component =
"free_list";
406 request->magic = 0x01020304;
439 talloc_free_children(request);
458 if (request->session_state_ctx) {
459 fr_assert(!request->parent || (request->session_state_ctx != request->parent->session_state_ctx));
465 request->magic = 0x01020304;
506 fr_pair_t *old = request->session_state_ctx;
508 fr_assert(request->session_state_ctx != NULL);
509 fr_assert(request->session_state_ctx != new_state);
519 request->session_state_ctx = new_state;
554 child->parent = NULL;
564 child->flags.detachable = 0;
578 PERROR(
"%s", __FUNCTION__);
582 PERROR(
"%s", __FUNCTION__);
596#ifdef WITH_VERIFY_PTR
600static void packet_verify(
char const *
file,
int line,
605 fr_fatal_assert_msg(packet,
"CONSISTENCY CHECK FAILED %s[%i]: fr_packet_t %s pointer was NULL",
608 parent = talloc_parent(packet);
615 "by %p (%s), but parented by %p (%s)",
632 if (
vp->
da->flags.is_raw)
continue;
634 if (
vp->
da->flags.internal)
continue;
636 if (
vp->
da->depth > 1) {
638 "by (%s), but it is instead at the top-level %s list",
659 (void)talloc_get_type_abort(request->request_ctx,
fr_pair_t);
660 fr_pair_list_verify(
file,
line, request->request_ctx, &request->request_pairs);
661 (void)talloc_get_type_abort(request->reply_ctx,
fr_pair_t);
662 fr_pair_list_verify(
file,
line, request->reply_ctx, &request->reply_pairs);
663 (void)talloc_get_type_abort(request->control_ctx,
fr_pair_t);
664 fr_pair_list_verify(
file,
line, request->control_ctx, &request->control_pairs);
665 (void)talloc_get_type_abort(request->session_state_ctx,
fr_pair_t);
669 TALLOC_CTX *
parent = talloc_parent(request->session_state_ctx);
672 "session_state_ctx must not be parented by another chunk, but is parented by %s",
673 talloc_get_name(talloc_parent(request->session_state_ctx)));
677 fr_pair_list_verify(
file,
line, request->session_state_ctx, &request->session_state_pairs);
678 fr_pair_list_verify(
file,
line, request->local_ctx, &request->local_pairs);
683 if (request->packet) {
684 packet_verify(
file,
line, request, request->packet, &request->request_pairs,
"request");
686 if (request->reply) {
687 packet_verify(
file,
line, request, request->reply, &request->reply_pairs,
"reply");
690 if (request->async) {
691 (void) talloc_get_type_abort(request->async,
fr_async_t);
692 fr_assert(talloc_parent(request->async) == request);
698 if (request_data_persistable(rd)) {
700 fr_assert(talloc_parent(rd) == request->session_state_ctx);
void request_verify(UNUSED char const *file, UNUSED int line, UNUSED request_t *request)
int fr_log_talloc_report(TALLOC_CTX const *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
#define fr_fatal_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_fatal_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define fr_dict_autofree(_to_free)
fr_dict_t const * fr_dict_proto_dict(fr_dict_t const *dict)
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
fr_dict_t const * fr_dict_internal(void)
#define fr_dict_autoload(_to_load)
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
static void fr_dlist_entry_init(fr_dlist_t *entry)
Initialise a linked list without metadata.
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
static bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
#define FR_HEAP_INDEX_INVALID
void * unlang_interpret_stack_alloc(TALLOC_CTX *ctx)
Allocate a new unlang stack.
Minimal data structure to use the new code.
void vlog_request(fr_log_type_t type, fr_log_lvl_t lvl, request_t *request, char const *file, int line, char const *fmt, va_list ap, void *uctx)
Send a log message to its destination, possibly including fields from the request.
fr_log_lvl_t lvl
Log messages with lvl >= to this should be logged.
void * uctx
Context to pass to the logging function.
log_dst_t * next
Next logging destination.
log_func_t func
Function to call to log to this destination.
@ L_DBG_LVL_DISABLE
Don't print messages.
@ L_DBG_LVL_OFF
No debug messages.
fr_packet_t * fr_packet_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new fr_packet_t.
@ FR_TYPE_GROUP
A grouping of other attributes.
fr_pair_t * fr_pair_root_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
A special allocation function which disables child autofree.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
static int request_child_init(request_t *child, request_t *parent)
fr_dict_attr_t const * request_attr_request
static int _request_global_init(UNUSED void *uctx)
static void request_log_init_orphan(request_t *request)
static int _request_local_free(request_t *request)
static request_t * request_alloc_pool(TALLOC_CTX *ctx)
#define list_init(_ctx, _list)
int request_slab_deinit(request_t *request)
Callback for slabs to deinitialise the request.
fr_dict_autoload_t request_dict[]
request_t * _request_local_alloc(char const *file, int line, TALLOC_CTX *ctx, request_type_t type, request_init_args_t const *args)
Allocate a request that's not in the free list.
static fr_dict_t const * dict_freeradius
fr_pair_t * request_state_replace(request_t *request, fr_pair_t *new_state)
Replace the session_state_ctx with a new one.
fr_dict_attr_t const * request_attr_control
static int request_detachable_init(request_t *child, request_t *parent)
fr_dict_attr_t const * request_attr_local
fr_dict_attr_t const * request_attr_state
fr_dict_attr_t const * request_attr_reply
fr_dict_attr_autoload_t request_dict_attr[]
void request_log_prepend(request_t *request, fr_log_t *log_dst, fr_log_lvl_t lvl)
Prepend another logging destination to the list.
int request_global_init(void)
int request_detach(request_t *child)
Unlink a subrequest from its parent.
static int _state_ctx_free(fr_pair_t *state)
fr_dict_attr_t const * request_attr_root
int _request_init(char const *file, int line, request_t *request, request_type_t type, request_init_args_t const *args)
Setup logging and other fields for a request.
static void request_log_init_child(request_t *child, request_t const *parent)
static void request_log_init_detachable(request_t *child, request_t const *parent)
static int _request_global_free(UNUSED void *uctx)
#define request_is_detached(_x)
#define REQUEST_POOL_HEADERS
@ REQUEST_TYPE_EXTERNAL
A request received on the wire.
@ REQUEST_TYPE_INTERNAL
A request generated internally.
@ REQUEST_TYPE_DETACHED
A request that was generated internally, but is now detached (not associated with a parent request....
#define request_is_detachable(_x)
#define REQUEST_POOL_SIZE
@ REQUEST_ACTIVE
Request is active (running or runnable)
Optional arguments for initialising requests.
void request_data_list_init(fr_dlist_head_t *data)
void * request_data_get(request_t *request, void const *unique_ptr, int unique_int)
Get opaque data from a request.
Per-request opaque data, added by modules.
#define request_data_talloc_add(_request, _unique_ptr, _unique_int, _type, _opaque, _free_on_replace, _free_on_parent, _persist)
Add opaque data to a request_t.
fr_aka_sim_id_type_t type
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
void * talloc_null_ctx(void)
Retrieve the current talloc NULL ctx.
#define talloc_get_type_abort_const
#define talloc_pooled_object(_ctx, _type, _num_subobjects, _total_subobjects_size)
#define fr_timer_armed(_ev)
#define PACKET_VERIFY(_x)
fr_pair_t * fr_pair_remove(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list without freeing.
#define fr_pair_list_foreach(_list_head, _iter)
Iterate over the contents of a fr_pair_list_t.
#define fr_strerror_const(_msg)