25RCSID(
"$Id: 6d0a283701e1c804cb11c364277b8d74e1468f7d $")
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");
284 .component =
"<pre-core>",
286 .detachable =
args &&
args->detachable,
313 if (
unlikely(!pair_root))
return -1;
314 request->pair_root = pair_root;
322 if (
args) memcpy(&request->pair_list, &
args->pair_list,
sizeof(request->pair_list));
324#define list_init(_ctx, _list) \
326 vp = fr_pair_afrom_da(_ctx, request_attr_##_list); \
327 if (unlikely(!vp)) { \
328 talloc_free(pair_root); \
329 memset(&request->pair_list, 0, sizeof(request->pair_list)); \
332 fr_pair_append(&pair_root->children, vp); \
333 request->pair_list._list = vp; \
336 if (!request->pair_list.request)
list_init(request->pair_root, request);
337 if (!request->pair_list.reply)
list_init(request->pair_root, reply);
338 if (!request->pair_list.control)
list_init(request->pair_root, control);
339 if (!request->pair_list.local)
list_init(request->pair_root, local);
340 if (!request->pair_list.state) {
356 if (
args->detachable) {
386 "alloced %s:%i: %s still in the timeout sublist",
389 request->name ? request->name :
"(null)");
391 "alloced %s:%i: %s still in the runnable heap ID %i",
394 request->name ? request->name :
"(null)", request->runnable);
396 RDEBUG3(
"Request deinitialising (%p)", request);
401 if (request->session_state_ctx) TALLOC_FREE(request->session_state_ctx);
406 memset(request, 0,
sizeof(*request));
409 request->component =
"free_list";
411 request->magic = 0x01020304;
440 RDEBUG4(
"Local request freed (%p)", request);
446 talloc_free_children(request);
465 if (request->session_state_ctx) {
466 fr_assert(!request->parent || (request->session_state_ctx != request->parent->session_state_ctx));
472 request->magic = 0x01020304;
513 fr_pair_t *old = request->session_state_ctx;
515 fr_assert(request->session_state_ctx != NULL);
516 fr_assert(request->session_state_ctx != new_state);
526 request->session_state_ctx = new_state;
561 child->parent = NULL;
571 child->flags.detachable = 0;
585 PERROR(
"%s", __FUNCTION__);
589 PERROR(
"%s", __FUNCTION__);
603#ifdef WITH_VERIFY_PTR
607static void packet_verify(
char const *
file,
int line,
612 fr_fatal_assert_msg(packet,
"CONSISTENCY CHECK FAILED %s[%i]: fr_packet_t %s pointer was NULL",
615 parent = talloc_parent(packet);
622 "by %p (%s), but parented by %p (%s)",
639 if (
vp->
da->flags.is_raw)
continue;
641 if (
vp->
da->flags.internal)
continue;
643 if (
vp->
da->depth > 1) {
645 "by (%s), but it is instead at the top-level %s list",
666 (void)talloc_get_type_abort(request->request_ctx,
fr_pair_t);
667 fr_pair_list_verify(
file,
line, request->request_ctx, &request->request_pairs);
668 (void)talloc_get_type_abort(request->reply_ctx,
fr_pair_t);
669 fr_pair_list_verify(
file,
line, request->reply_ctx, &request->reply_pairs);
670 (void)talloc_get_type_abort(request->control_ctx,
fr_pair_t);
671 fr_pair_list_verify(
file,
line, request->control_ctx, &request->control_pairs);
672 (void)talloc_get_type_abort(request->session_state_ctx,
fr_pair_t);
676 TALLOC_CTX *
parent = talloc_parent(request->session_state_ctx);
679 "session_state_ctx must not be parented by another chunk, but is parented by %s",
680 talloc_get_name(talloc_parent(request->session_state_ctx)));
684 fr_pair_list_verify(
file,
line, request->session_state_ctx, &request->session_state_pairs);
685 fr_pair_list_verify(
file,
line, request->local_ctx, &request->local_pairs);
690 if (request->packet) {
691 packet_verify(
file,
line, request, request->packet, &request->request_pairs,
"request");
693 if (request->reply) {
694 packet_verify(
file,
line, request, request->reply, &request->reply_pairs,
"reply");
697 if (request->async) {
698 (void) talloc_get_type_abort(request->async,
fr_async_t);
699 fr_assert(talloc_parent(request->async) == request);
705 if (request_data_persistable(rd)) {
707 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)
static bool fr_timer_armed(fr_timer_t *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)