The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
request.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: a51de1cb81c40f32c34b1ef77531e6467c22fb79 $
19 *
20 * @brief Functions for allocating requests and storing internal data in them.
21 * @file src/lib/server/request.c
22 *
23 * @copyright 2015 The FreeRADIUS server project
24 */
25RCSID("$Id: a51de1cb81c40f32c34b1ef77531e6467c22fb79 $")
26
27#include <freeradius-devel/server/request.h>
28#include <freeradius-devel/server/request_data.h>
29#include <freeradius-devel/unlang/interpret.h>
30
31#include <freeradius-devel/util/debug.h>
32#include <freeradius-devel/util/atexit.h>
33
35
38 { .out = &dict_freeradius, .proto = "freeradius" },
39 { NULL }
40};
41
48
51 { .out = &request_attr_root, .name = "root", .type = FR_TYPE_GROUP, .dict = &dict_freeradius },
52 { .out = &request_attr_request, .name = "request", .type = FR_TYPE_GROUP, .dict = &dict_freeradius },
53 { .out = &request_attr_reply, .name = "reply", .type = FR_TYPE_GROUP, .dict = &dict_freeradius },
54 { .out = &request_attr_control, .name = "control", .type = FR_TYPE_GROUP, .dict = &dict_freeradius },
55 { .out = &request_attr_state, .name = "session-state", .type = FR_TYPE_GROUP, .dict = &dict_freeradius },
56 { .out = &request_attr_local, .name = "local-variables", .type = FR_TYPE_GROUP, .dict = &dict_freeradius },
57 { NULL }
58};
59
60#ifndef NDEBUG
61static int _state_ctx_free(fr_pair_t *state)
62{
63 DEBUG4("state-ctx %p freed", state);
64
65 return 0;
66}
67#endif
68
69static inline void CC_HINT(always_inline) request_log_init_orphan(request_t *request)
70{
71 /*
72 * These may be changed later by request_pre_handler
73 */
74 request->log.lvl = fr_debug_lvl; /* Default to global debug level */
75 if (!request->log.dst) {
76 request->log.dst = talloc_zero(request, log_dst_t);
77 } else {
78 memset(request->log.dst, 0, sizeof(*request->log.dst));
79 }
80 request->log.dst->func = vlog_request;
81 request->log.dst->uctx = &default_log;
82 request->log.dst->lvl = fr_debug_lvl;
83}
84
85/** Prepend another logging destination to the list.
86 *
87
88 * @param request the request
89 * @param log_dst the logging destination
90 * @param lvl the new request debug lvl
91 */
93{
94 log_dst_t *dst;
95
96 if (lvl == L_DBG_LVL_DISABLE) {
97 while (request->log.dst) {
98 dst = request->log.dst->next;
99 talloc_free(request->log.dst);
100 request->log.dst = dst;
101 }
102 request->log.lvl = L_DBG_LVL_OFF;
103 return;
104 }
105
106 /*
107 * Remove a particular log destination.
108 */
109 if (lvl == L_DBG_LVL_OFF) {
110 log_dst_t **last;
111
112 last = &request->log.dst;
113 while (*last) {
114 dst = *last;
115 if (((fr_log_t *)dst->uctx)->parent == log_dst) {
116 *last = dst->next;
117 talloc_free(dst);
118 if (!request->log.dst) request->log.lvl = L_DBG_LVL_OFF;
119 return;
120 }
121
122 last = &(dst->next);
123 }
124
125 return;
126 }
127
128 /*
129 * Change the debug level of an existing destination.
130 */
131 for (dst = request->log.dst; dst != NULL; dst = dst->next) {
132 if (((fr_log_t *)dst->uctx)->parent == log_dst) {
133 dst->lvl = lvl;
134 if (lvl > request->log.lvl) request->log.lvl = lvl;
135 return;
136 }
137 }
138
139 /*
140 * Not found, add a new log destination.
141 */
142 MEM(dst = talloc_zero(request, log_dst_t));
143
144 dst->func = vlog_request;
145 dst->uctx = log_dst;
146
147 dst->lvl = lvl;
148 if (lvl > request->log.lvl) request->log.lvl = lvl;
149 dst->next = request->log.dst;
150
151 request->log.dst = dst;
152}
153
154static inline void CC_HINT(always_inline) request_log_init_child(request_t *child, request_t const *parent)
155{
156 /*
157 * Copy debug information.
158 */
159 memcpy(&(child->log), &(parent->log), sizeof(child->log));
160 child->log.indent.unlang = 0; /* Apart from the indent which we reset */
161 child->log.indent.module = 0; /* Apart from the indent which we reset */
162 child->log.lvl = parent->log.lvl;
163}
164
165static inline void CC_HINT(always_inline) request_log_init_detachable(request_t *child, request_t const *parent)
166{
168
169 /*
170 * Ensure that we use our own version of the logging
171 * information, and not the original request one.
172 */
173 child->log.dst = talloc_zero(child, log_dst_t);
174 memcpy(child->log.dst, parent->log.dst, sizeof(*child->log.dst));
175}
176
177static inline CC_HINT(always_inline) int request_detachable_init(request_t *child, request_t *parent)
178{
179 /*
180 * Associate the child with the parent, using the child's
181 * pointer as a unique identifier. Free it if the parent
182 * goes away, but don't persist it across
183 * challenge-response boundaries.
184 */
185 if (request_data_talloc_add(parent, child, 0, request_t, child, true, true, false) < 0) return -1;
186
187 return 0;
188}
189
190static inline CC_HINT(always_inline) int request_child_init(request_t *child, request_t *parent)
191{
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;
196 }
197
198 if ((parent->seq_start == 0) || (parent->number == parent->seq_start)) {
199 child->name = talloc_typed_asprintf(child, "%s.%" PRIu64, parent->name, child->number);
200 } else {
201 child->name = talloc_typed_asprintf(child, "(%s,%" PRIu64 ").%" PRIu64,
202 parent->name, parent->seq_start, child->number);
203 }
204 child->seq_start = 0; /* children always start with their own sequence */
205 child->parent = parent;
206
207 /*
208 * For new server support.
209 *
210 * FIXME: Key instead off of a "virtual server" data structure.
211 *
212 * FIXME: Permit different servers for inner && outer sessions?
213 */
214 child->packet = fr_packet_alloc(child, true);
215 if (!child->packet) {
216 talloc_free(child);
217 return -1;
218 }
219
220 child->reply = fr_packet_alloc(child, false);
221 if (!child->reply) {
222 talloc_free(child);
223 return -1;
224 }
225
226 return 0;
227}
228
229/** Setup logging and other fields for a request
230 *
231 * @param[in] file the request was allocated in.
232 * @param[in] line the request was allocated on.
233 * @param[in] request to (re)-initialise.
234 * @param[in] type of request to initialise.
235 * @param[in] args Other optional arguments.
236 */
237int _request_init(char const *file, int line,
238 request_t *request, request_type_t type,
240{
241 fr_dict_t const *dict;
242
243 /*
244 * Sanity checks for different requests types
245 */
246 switch (type) {
249
250 if (!fr_cond_assert_msg(!args->parent, "External requests must NOT have a parent")) return -1;
251
252 fr_assert(args->namespace);
253
254 dict = args->namespace;
255 break;
256
258 if (!args || !args->namespace) {
259 dict = fr_dict_internal();
260 } else {
261 dict = args->namespace;
262 }
263 break;
264
266 fr_assert_fail("Detached requests should start as type == REQUEST_TYPE_INTERNAL, "
267 "args->detachable and be detached later");
268 return -1;
269 }
270
271 *request = (request_t){
272#ifndef NDEBUG
273 .magic = REQUEST_MAGIC,
274#endif
275 .type = type,
276 .master_state = REQUEST_ACTIVE,
277 .proto_dict = fr_dict_proto_dict(dict),
278 .local_dict = dict,
279 .component = "<pre-core>",
280 .flags = {
281 .detachable = args && args->detachable,
282 },
283 .alloc_file = file,
284 .alloc_line = line
285 };
286
287
288 /*
289 * Initialise the stack
290 */
291 MEM(request->stack = unlang_interpret_stack_alloc(request));
292
293 /*
294 * Initialise the request data list
295 */
296 request_data_list_init(&request->data);
297
298 {
299 fr_pair_t *vp = NULL, *pair_root;
300
301 /*
302 * Alloc the pair root this is a
303 * special pair which does not
304 * free its children when it is
305 * freed.
306 */
307 pair_root = fr_pair_root_afrom_da(request, request_attr_root);
308 if (unlikely(!pair_root)) return -1;
309 request->pair_root = pair_root;
310
311 /*
312 * Copy all the pair lists over into
313 * the request. We then check for
314 * the any uninitialised lists and
315 * create them locally.
316 */
317 if (args) memcpy(&request->pair_list, &args->pair_list, sizeof(request->pair_list));
318
319#define list_init(_ctx, _list) \
320 do { \
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)); \
325 return -1; \
326 } \
327 fr_pair_append(&pair_root->children, vp); \
328 request->pair_list._list = vp; \
329 } while(0)
330
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) {
336 list_init(NULL, state);
337#ifndef NDEBUG
338 talloc_set_destructor(request->pair_list.state, _state_ctx_free);
339#endif
340 }
341 }
342
343 /*
344 * Initialise packets and additional
345 * fields if this is going to be a
346 * child request.
347 */
348 if (args && args->parent) {
349 if (request_child_init(request, args->parent) < 0) return -1;
350
351 if (args->detachable) {
352 if (request_detachable_init(request, args->parent) < 0) return -1;
353 request_log_init_detachable(request, args->parent);
354 } else {
355 request_log_init_child(request, args->parent);
356 }
357 } else {
359 }
360
361 /*
362 * This is only used by src/lib/io/worker.c
363 */
364 fr_dlist_entry_init(&request->listen_entry);
365
366 return 0;
367}
368
369/** Callback for slabs to deinitialise the request
370 *
371 * Does not need to be called for local requests.
372 *
373 * @param[in] request deinitialise
374 * @return
375 * - 0 in the request was deinitialised.
376 * - -1 if the request is in an unexpected state.
377 */
379{
380 fr_assert_msg(!fr_timer_armed(request->timeout),
381 "alloced %s:%i: %s still in the timeout sublist",
382 request->alloc_file,
383 request->alloc_line,
384 request->name ? request->name : "(null)");
385 fr_assert_msg(!fr_heap_entry_inserted(request->runnable),
386 "alloced %s:%i: %s still in the runnable heap ID %i",
387 request->alloc_file,
388 request->alloc_line,
389 request->name ? request->name : "(null)", request->runnable);
390
391 RDEBUG3("Request deinitialising (%p)", request);
392
393 /*
394 * state_ctx is parented separately.
395 */
396 if (request->session_state_ctx) TALLOC_FREE(request->session_state_ctx);
397
398 /*
399 * Zero out everything.
400 */
401 memset(request, 0, sizeof(*request));
402
403#ifndef NDEBUG
404 request->component = "free_list";
405 request->runnable = FR_HEAP_INDEX_INVALID;
406 request->magic = 0x01020304; /* set the request to be nonsense */
407#endif
408
409 return 0;
410}
411
412static inline CC_HINT(always_inline) request_t *request_alloc_pool(TALLOC_CTX *ctx)
413{
414 request_t *request;
415
416 /*
417 * Only allocate requests in the NULL
418 * ctx. There's no scenario where it's
419 * appropriate to allocate them in a
420 * pool, and using a strict talloc
421 * hierarchy means that child requests
422 * cannot be returned to a free list
423 * and would have to be freed.
424 */
425 MEM(request = talloc_pooled_object(ctx, request_t,
428 fr_assert(ctx != request);
429
430 return request;
431}
432
433static int _request_local_free(request_t *request)
434{
435 /*
436 * Ensure anything that might reference the request is
437 * freed before it is.
438 */
439 talloc_free_children(request);
440
441 /*
442 * state_ctx is parented separately.
443 *
444 * The reason why it's OK to do this, is if the state attributes
445 * need to persist across requests, they will already have been
446 * moved to a fr_state_entry_t, with the state pointers in the
447 * request being set to NULL, before the request is freed/
448 *
449 * Note also that we do NOT call TALLOC_FREE(), which
450 * sets state_ctx=NULL. We don't control the order in
451 * which talloc frees the children. And the parents
452 * state_ctx pointer needs to stick around so that all of
453 * the children can check it.
454 *
455 * If this assertion hits, it means that someone didn't
456 * call fr_state_store_in_parent()
457 */
458 if (request->session_state_ctx) {
459 fr_assert(!request->parent || (request->session_state_ctx != request->parent->session_state_ctx));
460
461 talloc_free(request->session_state_ctx);
462 }
463
464#ifndef NDEBUG
465 request->magic = 0x01020304; /* set the request to be nonsense */
466#endif
467
468 return 0;
469}
470
471/** Allocate a request that's not in the free list
472 *
473 * This can be useful if modules need a persistent request for their own purposes
474 * which needs to be outside of the normal free list, so that it can be freed
475 * when the module requires, not when the thread destructor runs.
476 */
477request_t *_request_local_alloc(char const *file, int line, TALLOC_CTX *ctx,
479{
480 request_t *request;
481
482 request = request_alloc_pool(ctx);
483 if (_request_init(file, line, request, type, args) < 0) return NULL;
484
485 talloc_set_destructor(request, _request_local_free);
486
487 return request;
488}
489
490/** Replace the session_state_ctx with a new one.
491 *
492 * NOTHING should rewrite request->session_state_ctx.
493 *
494 * It's now a pair, and is stored in request->pair_root.
495 * So it's wrong for anyone other than this function to play games with it.
496 *
497 * @param[in] request to replace the state of.
498 * @param[in] new_state state to assign to the request.
499 * May be NULL in which case a new_state state will
500 * be alloced and assigned.
501 *
502 * @return the fr_pair_t containing the old state list.
503 */
505{
506 fr_pair_t *old = request->session_state_ctx;
507
508 fr_assert(request->session_state_ctx != NULL);
509 fr_assert(request->session_state_ctx != new_state);
510
511 fr_pair_remove(&request->pair_root->children, old);
512
513 /*
514 * Save (or delete) the existing state, and re-initialize
515 * it with a brand new one.
516 */
517 if (!new_state) MEM(new_state = fr_pair_afrom_da(NULL, request_attr_state));
518
519 request->session_state_ctx = new_state;
520
521 fr_pair_append(&request->pair_root->children, new_state);
522
523 return old;
524}
525
526/** Unlink a subrequest from its parent
527 *
528 * @note This should be used for requests in preparation for freeing them.
529 *
530 * @param[in] child request to unlink.
531 * @return
532 * - 0 on success.
533 * - -1 on failure.
534 */
536{
537 request_t *request = child->parent;
538
539 /*
540 * Already detached or not detachable
541 */
542 if (request_is_detached(child)) return 0;
543
544 if (!request_is_detachable(child)) {
545 fr_strerror_const("Request is not detachable");
546 return -1;
547 }
548
549 /*
550 * Unlink the child from the parent.
551 */
552 request_data_get(request, child, 0);
553
554 child->parent = NULL;
555
556 /*
557 * Request is now detached
558 */
559 child->type = REQUEST_TYPE_DETACHED;
560
561 /*
562 * ...and is no longer detachable.
563 */
564 child->flags.detachable = 0;
565
566 return 0;
567}
568
569static int _request_global_free(UNUSED void *uctx)
570{
572 return 0;
573}
574
575static int _request_global_init(UNUSED void *uctx)
576{
578 PERROR("%s", __FUNCTION__);
579 return -1;
580 }
582 PERROR("%s", __FUNCTION__);
584 return -1;
585 }
586 return 0;
587}
588
590{
591 int ret;
592 fr_atexit_global_once_ret(&ret, _request_global_init, _request_global_free, NULL);
593 return ret;
594}
595
596#ifdef WITH_VERIFY_PTR
597/*
598 * Verify a packet.
599 */
600static void packet_verify(char const *file, int line,
601 request_t const *request, fr_packet_t const *packet, fr_pair_list_t *list, char const *type)
602{
603 TALLOC_CTX *parent;
604
605 fr_fatal_assert_msg(packet, "CONSISTENCY CHECK FAILED %s[%i]: fr_packet_t %s pointer was NULL",
606 file, line, type);
607
608 parent = talloc_parent(packet);
609 if (parent != request) {
610 fr_log_talloc_report(packet);
612
613
614 fr_fatal_assert_fail("CONSISTENCY CHECK FAILED %s[%i]: Expected fr_packet_t %s to be parented "
615 "by %p (%s), but parented by %p (%s)",
616 file, line, type, request, talloc_get_name(request),
617 parent, parent ? talloc_get_name(parent) : "NULL");
618 }
619
620 /*
621 * Enforce nesting at the top level. This catches minor programming bugs in the server core.
622 *
623 * If we care more, we could do these checks recursively. But the tmpl_tokenize code already
624 * enforces parent / child namespaces. So the end user shouldn't be able to break the parenting.
625 *
626 * This code really only checks for programming bugs where the C code creates a pair, and then
627 * adds it to the wrong list. This was happening during the transition from flat to nested, as
628 * the code was in the middle of being fixed. It should only happen now if the programmer
629 * forgets, and uses the wrong APIs.
630 */
631 fr_pair_list_foreach(list, vp) {
632 if (vp->da->flags.is_raw) continue;
633
634 if (vp->da->flags.internal) continue;
635
636 if (vp->da->depth > 1) {
637 fr_fatal_assert_fail("CONSISTENCY CHECK FAILED %s[%i]: Expected fr_pair_t %s to be parented "
638 "by (%s), but it is instead at the top-level %s list",
639 file, line, vp->da->name, vp->da->parent->name, type);
640 }
641 }
642
643 PACKET_VERIFY(packet);
644}
645
646/*
647 * Catch horrible talloc errors.
648 */
649void request_verify(char const *file, int line, request_t const *request)
650{
651 request_data_t *rd = NULL;
652
653 fr_fatal_assert_msg(request, "CONSISTENCY CHECK FAILED %s[%i]: request_t pointer was NULL", file, line);
654
655 (void) talloc_get_type_abort_const(request, request_t);
656
657 fr_assert(request->magic == REQUEST_MAGIC);
658
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);
666
667#ifndef NDEBUG
668 {
669 TALLOC_CTX *parent = talloc_parent(request->session_state_ctx);
670
671 fr_assert_msg((parent == NULL) || (parent == talloc_null_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)));
674 }
675#endif
676
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);
679
680 fr_assert(request->proto_dict != NULL);
681 fr_assert(request->local_dict != NULL);
682
683 if (request->packet) {
684 packet_verify(file, line, request, request->packet, &request->request_pairs, "request");
685 }
686 if (request->reply) {
687 packet_verify(file, line, request, request->reply, &request->reply_pairs, "reply");
688 }
689
690 if (request->async) {
691 (void) talloc_get_type_abort(request->async, fr_async_t);
692 fr_assert(talloc_parent(request->async) == request);
693 }
694
695 while ((rd = fr_dlist_next(&request->data, rd))) {
696 (void) talloc_get_type_abort(rd, request_data_t);
697
698 if (request_data_persistable(rd)) {
699 fr_assert(request->session_state_ctx);
700 fr_assert(talloc_parent(rd) == request->session_state_ctx);
701 } else {
702 fr_assert(talloc_parent(rd) == request);
703 }
704 }
705}
706#endif
int const char * file
Definition acutest.h:702
va_list args
Definition acutest.h:770
int const char int line
Definition acutest.h:702
void request_verify(UNUSED char const *file, UNUSED int line, UNUSED request_t *request)
#define RCSID(id)
Definition build.h:485
#define unlikely(_x)
Definition build.h:383
#define UNUSED
Definition build.h:317
int fr_log_talloc_report(TALLOC_CTX const *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
Definition debug.c:1147
#define fr_fatal_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:191
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:210
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
Definition debug.h:216
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:156
#define fr_fatal_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:184
#define MEM(x)
Definition debug.h:36
#define fr_dict_autofree(_to_free)
Definition dict.h:862
fr_dict_t const * fr_dict_proto_dict(fr_dict_t const *dict)
Definition dict_util.c:4974
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:272
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:285
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.
Definition dict_util.c:4092
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:4612
#define fr_dict_autoload(_to_load)
Definition dict.h:859
Specifies an attribute which must be present for the module to function.
Definition dict.h:271
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:284
static void fr_dlist_entry_init(fr_dlist_t *entry)
Initialise a linked list without metadata.
Definition dlist.h:138
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
Definition dlist.h:555
static bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
Definition heap.h:124
#define FR_HEAP_INDEX_INVALID
Definition heap.h:83
void * unlang_interpret_stack_alloc(TALLOC_CTX *ctx)
Allocate a new unlang stack.
Definition interpret.c:1063
Minimal data structure to use the new code.
Definition listen.h:59
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.
Definition log.c:293
#define PERROR(_fmt,...)
Definition log.h:228
fr_log_lvl_t lvl
Log messages with lvl >= to this should be logged.
Definition log.h:73
#define RDEBUG3(fmt,...)
Definition log.h:343
#define DEBUG4(_fmt,...)
Definition log.h:267
void * uctx
Context to pass to the logging function.
Definition log.h:72
log_dst_t * next
Next logging destination.
Definition log.h:74
log_func_t func
Function to call to log to this destination.
Definition log.h:71
Definition log.h:70
talloc_free(reap)
int fr_debug_lvl
Definition log.c:40
fr_log_t default_log
Definition log.c:288
fr_log_lvl_t
Definition log.h:67
@ L_DBG_LVL_DISABLE
Don't print messages.
Definition log.h:68
@ L_DBG_LVL_OFF
No debug messages.
Definition log.h:69
fr_packet_t * fr_packet_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new fr_packet_t.
Definition packet.c:38
@ 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.
Definition pair.c:245
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition pair.c:1347
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.
Definition pair.c:285
#define fr_assert(_expr)
Definition rad_assert.h:38
static int request_child_init(request_t *child, request_t *parent)
Definition request.c:190
fr_dict_attr_t const * request_attr_request
Definition request.c:43
static int _request_global_init(UNUSED void *uctx)
Definition request.c:575
static void request_log_init_orphan(request_t *request)
Definition request.c:69
static int _request_local_free(request_t *request)
Definition request.c:433
static request_t * request_alloc_pool(TALLOC_CTX *ctx)
Definition request.c:412
#define list_init(_ctx, _list)
int request_slab_deinit(request_t *request)
Callback for slabs to deinitialise the request.
Definition request.c:378
fr_dict_autoload_t request_dict[]
Definition request.c:37
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.
Definition request.c:477
static fr_dict_t const * dict_freeradius
Definition request.c:34
fr_pair_t * request_state_replace(request_t *request, fr_pair_t *new_state)
Replace the session_state_ctx with a new one.
Definition request.c:504
fr_dict_attr_t const * request_attr_control
Definition request.c:45
static int request_detachable_init(request_t *child, request_t *parent)
Definition request.c:177
fr_dict_attr_t const * request_attr_local
Definition request.c:47
fr_dict_attr_t const * request_attr_state
Definition request.c:46
fr_dict_attr_t const * request_attr_reply
Definition request.c:44
fr_dict_attr_autoload_t request_dict_attr[]
Definition request.c:50
void request_log_prepend(request_t *request, fr_log_t *log_dst, fr_log_lvl_t lvl)
Prepend another logging destination to the list.
Definition request.c:92
int request_global_init(void)
Definition request.c:589
int request_detach(request_t *child)
Unlink a subrequest from its parent.
Definition request.c:535
static int _state_ctx_free(fr_pair_t *state)
Definition request.c:61
fr_dict_attr_t const * request_attr_root
Definition request.c:42
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.
Definition request.c:237
static void request_log_init_child(request_t *child, request_t const *parent)
Definition request.c:154
static void request_log_init_detachable(request_t *child, request_t const *parent)
Definition request.c:165
static int _request_global_free(UNUSED void *uctx)
Definition request.c:569
#define request_is_detached(_x)
Definition request.h:186
#define REQUEST_MAGIC
Definition request.h:57
#define REQUEST_POOL_HEADERS
Definition request.h:66
request_type_t
Definition request.h:177
@ REQUEST_TYPE_EXTERNAL
A request received on the wire.
Definition request.h:178
@ REQUEST_TYPE_INTERNAL
A request generated internally.
Definition request.h:179
@ REQUEST_TYPE_DETACHED
A request that was generated internally, but is now detached (not associated with a parent request....
Definition request.h:180
#define request_is_detachable(_x)
Definition request.h:187
#define REQUEST_POOL_SIZE
Definition request.h:79
@ REQUEST_ACTIVE
Request is active (running or runnable)
Definition request.h:87
Optional arguments for initialising requests.
Definition request.h:283
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
fr_pair_t * vp
Definition log.h:96
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition talloc.c:488
void * talloc_null_ctx(void)
Retrieve the current talloc NULL ctx.
Definition talloc.c:49
#define talloc_get_type_abort_const
Definition talloc.h:282
#define talloc_pooled_object(_ctx, _type, _num_subobjects, _total_subobjects_size)
Definition talloc.h:180
#define fr_timer_armed(_ev)
Definition timer.h:117
#define PACKET_VERIFY(_x)
Definition packet.h:42
fr_pair_t * fr_pair_remove(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list without freeing.
Definition pair_inline.c:93
#define fr_pair_list_foreach(_list_head, _iter)
Iterate over the contents of a fr_pair_list_t.
Definition pair.h:261
static fr_slen_t parent
Definition pair.h:845
#define fr_strerror_const(_msg)
Definition strerror.h:223