]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Change process and signal functions to pass the current frame
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 12 Mar 2021 14:42:34 +0000 (14:42 +0000)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 12 Mar 2021 15:17:42 +0000 (15:17 +0000)
For signal functions this is important because all frames are signalled.  For process functions it removes significant amounts of boilerplate.

28 files changed:
src/lib/io/worker.c
src/lib/server/request.c
src/lib/server/signal.h
src/lib/unlang/base.h
src/lib/unlang/call.c
src/lib/unlang/caller.c
src/lib/unlang/condition.c
src/lib/unlang/foreach.c
src/lib/unlang/function.c
src/lib/unlang/function.h [new file with mode: 0644]
src/lib/unlang/group.c
src/lib/unlang/group_priv.h
src/lib/unlang/interpret.c
src/lib/unlang/interpret.h
src/lib/unlang/load_balance.c
src/lib/unlang/map.c
src/lib/unlang/module.c
src/lib/unlang/module_priv.h
src/lib/unlang/parallel.c
src/lib/unlang/parallel_priv.h
src/lib/unlang/return.c
src/lib/unlang/return_priv.h
src/lib/unlang/subrequest.c
src/lib/unlang/switch.c
src/lib/unlang/tmpl.c
src/lib/unlang/unlang_priv.h
src/lib/unlang/xlat.c
src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c

index a6b1a990b92fcaca767c83c62906d7a05c11e38d..f1a979f56832ba2340de95f0402ceeb1b80905e3 100644 (file)
@@ -1239,19 +1239,26 @@ void fr_worker_post_event(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void
 /** Asynchronously add a request_t to a worker thread
  *
  *  When we don't know what the worker is...
+ *
+ * @param[in] request          to add.
+ * @param[in] process          module method to call when the request is executed.
+ * @param[in] uctx             to pass to the process method.
+ * @return
+ *     - 0 on success.
+ *     - -1 on failure.
  */
-int fr_worker_request_add(request_t *request, module_method_t process, void *ctx)
+int fr_worker_request_add(request_t *request, module_method_t process, void *uctx)
 {
        fr_worker_t *worker;
        fr_time_t now;
 
-       if (!request || !process) {
+       if (unlikely(!request || !process)) {
                fr_strerror_const("Invalid arguments");
                return -1;
        }
 
        worker = thread_local_worker;
-       if (!worker) {
+       if (unlikely(!worker)) {
                fr_strerror_const("No worker has been defined");
                return -1;
        }
@@ -1262,7 +1269,7 @@ int fr_worker_request_add(request_t *request, module_method_t process, void *ctx
 
        fr_assert(request_is_internal(request));
        request->async->process = process;
-       request->async->process_inst = ctx;
+       request->async->process_inst = uctx;
 
        worker_request_time_tracking_start(worker, request, now);
 
index 6ac42046a5224ea1969dfc6145def50340c9258a..d975472c86941259f4dbf9ba541da9aa27b3782b 100644 (file)
@@ -553,6 +553,13 @@ int request_detach(request_t *child)
 
        fr_assert(request != NULL);
 
+       /*
+        *      Let any signal handler that cares
+        *      know that the child is about to
+        *      be detached.
+        */
+       unlang_interpret_signal(child, FR_SIGNAL_DETACH);
+
        /*
         *      Unlink the child from the parent.
         */
index c93a4912c118aa9aad11974ec654e013e1c7a021..b92f7be95c1d694dd35cb830ccf2b4b195aacb0c 100644 (file)
@@ -40,6 +40,7 @@ typedef enum fr_state_signal_t {      /* server action */
                                        ///< with this, the module should stop processing
                                        ///< the request and cleanup anything it's done.
        FR_SIGNAL_DUP,                  //!< A duplicate request was received.
+       FR_SIGNAL_DETACH                //!< Request is being detached from its parent.
 } fr_state_signal_t;
 
 #ifdef __cplusplus
index d2233fe76663bdb18ee65d7cd7ebedd6c42799f0..8856bd67efb9f3130bab38484061a5a2920b4e45 100644 (file)
@@ -24,6 +24,7 @@
  * @copyright 2016-2019 The FreeRADIUS server project
  */
 #include <freeradius-devel/unlang/compile.h>
+#include <freeradius-devel/unlang/function.h>
 #include <freeradius-devel/unlang/interpret.h>
 #include <freeradius-devel/unlang/module.h>
 #include <freeradius-devel/unlang/subrequest.h>
 extern "C" {
 #endif
 
-#define UNLANG_STACK_MAX (64)          //!< The maximum depth of the stack.
-#define UNLANG_FRAME_PRE_ALLOC (128)   //!< How much memory we pre-alloc for each frame.
-
 bool           unlang_section(CONF_SECTION *cs);
 
-void           unlang_register(int type, unlang_op_t *op);
-
 int            unlang_init(void);
 
 void           unlang_free(void);
index e5eef50e63e67dee492135a8304d1ed7f9952fd6..73ae1237316b56f7f777d79a287f6249c7f67501 100644 (file)
@@ -30,13 +30,11 @@ RCSID("$Id$")
 #include "call_priv.h"
 #include "unlang_priv.h"
 
-static unlang_action_t unlang_call_process(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_call_process(rlm_rcode_t *p_result, request_t *request,
+                                          unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_call_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_call_t);
-       unlang_t                        *instruction = frame->instruction;
-       unlang_group_t                  *g = unlang_generic_to_group(instruction);
+       unlang_group_t                  *g = unlang_generic_to_group(frame->instruction);
 
        rlm_rcode_t                     rcode;
        unlang_action_t                 ua;
@@ -83,13 +81,10 @@ static unlang_action_t unlang_call_process(rlm_rcode_t *p_result, request_t *req
        return UNLANG_ACTION_CALCULATE_RESULT;
 }
 
-static unlang_action_t unlang_call_frame_init(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_call_frame_init(rlm_rcode_t *p_result, request_t *request,
+                                             unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_call_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_call_t);
-       unlang_t                        *instruction = frame->instruction;
-
        unlang_group_t                  *g;
        unlang_call_t                   *gext;
        char const                      *server;
@@ -105,7 +100,7 @@ static unlang_action_t unlang_call_frame_init(rlm_rcode_t *p_result, request_t *
         *      can still be side effects from executing the virtual
         *      server.
         */
-       g = unlang_generic_to_group(instruction);
+       g = unlang_generic_to_group(frame->instruction);
        gext = unlang_group_to_call(g);
        server = cf_section_name2(gext->server_cs);
 
@@ -141,7 +136,7 @@ static unlang_action_t unlang_call_frame_init(rlm_rcode_t *p_result, request_t *
                .prev_server_cs = request->server_cs,
        };
 
-       return unlang_call_process(p_result, request);
+       return unlang_call_process(p_result, request, frame);
 }
 
 /** Push a call to a virtual server onto the stack for evaluation
index a446d7f7992c49d55538ecf22e83e0082fe03af7..821295b43aa53dd8f5c2a00c63a2e8f076454fbe 100644 (file)
@@ -30,17 +30,10 @@ RCSID("$Id$")
 #include "unlang_priv.h"
 #include "group_priv.h"
 
-static unlang_action_t unlang_caller(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_caller(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_t                        *instruction = frame->instruction;
-
-       unlang_group_t                  *g;
-       unlang_caller_t         *gext;
-
-       g = unlang_generic_to_group(instruction);
-       gext = unlang_group_to_caller(g);
+       unlang_group_t                  *g = unlang_generic_to_group(frame->instruction);
+       unlang_caller_t                 *gext = unlang_group_to_caller(g);
 
        fr_assert(g->num_children > 0); /* otherwise the compilation is broken */
 
@@ -55,7 +48,7 @@ static unlang_action_t unlang_caller(rlm_rcode_t *p_result, request_t *request)
        /*
         *      The dictionary matches.  Go recurse into its' children.
         */
-       return unlang_group(p_result, request);
+       return unlang_group(p_result, request, frame);
 }
 
 
index d5292ae3c0c4507b61ca5eac0ec37f316cc06275..963de7b97738f6479e06853d94e6fdf579bfef45 100644 (file)
@@ -28,18 +28,12 @@ RCSID("$Id$")
 #include "group_priv.h"
 #include "unlang_priv.h"
 
-static unlang_action_t unlang_if(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_if(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
        int                     condition;
-       unlang_stack_t          *stack = request->stack;
-       unlang_stack_frame_t    *frame = &stack->frame[stack->depth];
-       unlang_t                *instruction = frame->instruction;
+       unlang_group_t          *g = unlang_generic_to_group(frame->instruction);
+       unlang_cond_t           *gext = unlang_group_to_cond(g);
 
-       unlang_group_t          *g;
-       unlang_cond_t   *gext;
-
-       g = unlang_generic_to_group(instruction);
-       gext = unlang_group_to_cond(g);
        fr_assert(gext->cond != NULL);
 
        condition = cond_eval(request, *p_result, gext->cond);
@@ -79,7 +73,7 @@ static unlang_action_t unlang_if(rlm_rcode_t *p_result, request_t *request)
        /*
         *      We took the "if".  Go recurse into its' children.
         */
-       return unlang_group(p_result, request);
+       return unlang_group(p_result, request, frame);
 }
 
 void unlang_condition_init(void)
index 0dea4f9175732a928e7208dedf7adefdcc6d5e14..20c12dd7e1ea87df6d0be1bfd07f843d8485bba8 100644 (file)
@@ -75,19 +75,11 @@ static int _free_unlang_frame_state_foreach(unlang_frame_state_foreach_t *state)
        return 0;
 }
 
-static unlang_action_t unlang_foreach_next(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_foreach_next(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
        fr_pair_t                       *vp;
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_t                        *instruction = frame->instruction;
-       unlang_frame_state_foreach_t    *foreach = NULL;
-       unlang_group_t                  *g;
-
-       g = unlang_generic_to_group(instruction);
-
-       foreach = talloc_get_type_abort(frame->state, unlang_frame_state_foreach_t);
-
+       unlang_frame_state_foreach_t    *foreach = talloc_get_type_abort(frame->state, unlang_frame_state_foreach_t);
+       unlang_group_t                  *g = unlang_generic_to_group(frame->instruction);
        vp = fr_dcursor_current(&foreach->cursor);
        if (!vp) {
                *p_result = frame->result;
@@ -126,24 +118,17 @@ static unlang_action_t unlang_foreach_next(rlm_rcode_t *p_result, request_t *req
 }
 
 
-static unlang_action_t unlang_foreach(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_foreach(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame;
-       unlang_t                        *instruction;
        unlang_frame_state_foreach_t    *foreach = NULL;
-
-       unlang_group_t                  *g;
-       unlang_foreach_t                *gext;
+       unlang_stack_t                  *stack = request->stack;
+       unlang_group_t                  *g = unlang_generic_to_group(frame->instruction);
+       unlang_foreach_t                *gext = unlang_group_to_foreach(g);
 
        int                             i, foreach_depth = 0;
        fr_pair_list_t                  vps;
 
-       frame = &stack->frame[stack->depth];
        fr_pair_list_init(&vps);
-       instruction = frame->instruction;
-       g = unlang_generic_to_group(instruction);
-       gext = unlang_group_to_foreach(g);
 
        /*
         *      Ensure any breaks terminate here...
@@ -154,7 +139,7 @@ static unlang_action_t unlang_foreach(rlm_rcode_t *p_result, request_t *request)
         *      Figure out foreach depth by walking back up the stack
         */
        if (stack->depth > 0) for (i = (stack->depth - 1); i >= 0; i--) {
-                       unlang_t *our_instruction;
+                       unlang_t const *our_instruction;
                        our_instruction = stack->frame[i].instruction;
                        if (!our_instruction || (our_instruction->type != UNLANG_TYPE_FOREACH)) continue;
                        foreach_depth++;
@@ -166,7 +151,7 @@ static unlang_action_t unlang_foreach(rlm_rcode_t *p_result, request_t *request)
                return UNLANG_ACTION_CALCULATE_RESULT;
        }
 
-       MEM(frame->state = foreach = talloc_zero(stack, unlang_frame_state_foreach_t));
+       MEM(frame->state = foreach = talloc_zero(request->stack, unlang_frame_state_foreach_t));
        fr_pair_list_init(&foreach->vps);
 
        /*
@@ -191,16 +176,12 @@ static unlang_action_t unlang_foreach(rlm_rcode_t *p_result, request_t *request)
        talloc_set_destructor(foreach, _free_unlang_frame_state_foreach);
 
        frame->process = unlang_foreach_next;
-       return unlang_foreach_next(p_result, request);
+       return unlang_foreach_next(p_result, request, frame);
 }
 
-static unlang_action_t unlang_break(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_break(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t          *stack = request->stack;
-       unlang_stack_frame_t    *frame = &stack->frame[stack->depth];
-       unlang_t                *instruction = frame->instruction;
-
-       RDEBUG2("%s", unlang_ops[instruction->type].name);
+       RDEBUG2("%s", unlang_ops[frame->instruction->type].name);
 
        *p_result = frame->result;
 
@@ -208,7 +189,7 @@ static unlang_action_t unlang_break(rlm_rcode_t *p_result, request_t *request)
         *      Stop at the next break point, or if we hit
         *      the a top frame.
         */
-       return unwind_to_break(stack);
+       return unwind_to_break(request->stack);
 }
 
 /** Implements the Foreach-Variable-X
index f09405ea4304b5484ebd7766e3ff5ef22461be03..b0789f62b94e910e00b5f695410d9555e222f296 100644 (file)
  * @file unlang/function.c
  * @brief Unlang "function" keyword evaluation.
 
- * @copyright 2018 The FreeRADIUS server project
- * @copyright 2018 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
+ * @copyright 2018,2021 The FreeRADIUS server project
+ * @copyright 2018,2021 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
  */
 RCSID("$Id$")
 
 #include "unlang_priv.h"
+#include "function.h"
 
 /*
  *     Some functions differ mainly in their parsing
@@ -33,6 +34,7 @@ RCSID("$Id$")
 typedef struct {
        unlang_function_t               func;                   //!< To call when going down the stack.
        unlang_function_t               repeat;                 //!< To call when going back up the stack.
+       unlang_function_signal_t        signal;                 //!< Signal function to call.
        void                            *uctx;                  //!< Uctx to pass to function.
 } unlang_frame_state_func_t;
 
@@ -56,15 +58,30 @@ static unlang_t function_instruction = {
        }
 };
 
+/** Generic signal handler
+ *
+ * @param[in] request          being signalled.
+ * @param[in] frame            being signalled.
+ * @param[in] action           Type of signal.
+ */
+static void unlang_function_signal(request_t *request,
+                                  unlang_stack_frame_t *frame, fr_state_signal_t action)
+{
+       unlang_frame_state_func_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_func_t);
+
+       if (!state->signal) return;
+
+       state->signal(request, action, state->uctx);
+}
+
 /** Call a generic function
  *
- * @param[out] p_result        The frame result.
- * @param[in] request  The current request.
+ * @param[out] p_result                The frame result.
+ * @param[in] request          The current request.
+ * @param[in] frame            The current frame.
  */
-static unlang_action_t unlang_function_call(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_function_call(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_func_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_func_t);
        unlang_action_t                 ua;
        char const                      *caller;
@@ -76,9 +93,9 @@ static unlang_action_t unlang_function_call(rlm_rcode_t *p_result, request_t *re
        caller = request->module;
        request->module = NULL;
        if (!is_repeatable(frame)) {
-               ua = state->func(p_result, NULL, request, state->uctx);
+               ua = state->func(p_result, &frame->priority, request, state->uctx);
        } else {
-               ua = state->repeat(p_result, NULL, request, state->uctx);
+               ua = state->repeat(p_result, &frame->priority, request, state->uctx);
        }
        request->module = caller;
 
@@ -94,12 +111,14 @@ static unlang_action_t unlang_function_call(rlm_rcode_t *p_result, request_t *re
  * @param[in] func     to call going up the stack.
  * @param[in] repeat   function to call going back down the stack (may be NULL).
  *                     This may be the same as func.
+ * @param[in] signal   function to call if the request is signalled.
  * @param[in] uctx     to pass to func.
  * @return
  *     - 0 on success.
  *     - -1 on failure.
  */
-int unlang_interpret_push_function(request_t *request, unlang_function_t func, unlang_function_t repeat, void *uctx)
+int unlang_interpret_push_function(request_t *request, unlang_function_t func, unlang_function_t repeat,
+                                  unlang_function_signal_t signal, void *uctx)
 {
        unlang_stack_t                  *stack = request->stack;
        unlang_stack_frame_t            *frame;
@@ -125,6 +144,7 @@ int unlang_interpret_push_function(request_t *request, unlang_function_t func, u
        state = frame->state;
        state->func = func;
        state->repeat = repeat;
+       state->signal = signal;
        state->uctx = uctx;
 
        return 0;
@@ -136,6 +156,7 @@ void unlang_function_init(void)
                           &(unlang_op_t){
                                .name = "function",
                                .interpret = unlang_function_call,
+                               .signal = unlang_function_signal,
                                .debug_braces = false,
                                .frame_state_size = sizeof(unlang_frame_state_func_t),
                                .frame_state_name = "unlang_frame_state_func_t",
diff --git a/src/lib/unlang/function.h b/src/lib/unlang/function.h
new file mode 100644 (file)
index 0000000..a4da043
--- /dev/null
@@ -0,0 +1,62 @@
+#pragma once
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * $Id$
+ *
+ * @file unlang/function.h
+ * @brief Declarations for generic unlang functions.
+ *
+ * @copyright 2021 The FreeRADIUS server project
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <freeradius-devel/server/rcode.h>
+#include <freeradius-devel/server/request.h>
+#include <freeradius-devel/server/signal.h>
+
+/** A generic function pushed by a module or xlat to functions deeper in the C call stack to create resumption points
+ *
+ * @param[in] request          The current request.
+ * @param[in,out] uctx         Provided by whatever pushed the function.  Is opaque to the
+ *                             interpreter, but should be usable by the function.
+ *                             All input (args) and output will be done using this structure.
+ * @return an #unlang_action_t.
+ */
+typedef unlang_action_t (*unlang_function_t)(rlm_rcode_t *p_result, int *priority, request_t *request, void *uctx);
+
+/** Function to call if the request was signalled
+ *
+ * @param[in] request          The current request.
+ * @param[in] action           We're being signalled with.
+ * @param[in,out] uctx         Provided by whatever pushed the function.  Is opaque to the
+ *                             interpreter, but should be usable by the function.
+ *                             All input (args) and output will be done using this structure.
+ */
+typedef void (*unlang_function_signal_t)(request_t *request, fr_state_signal_t action, void *uctx);
+
+int            unlang_interpret_push_function(request_t *request,
+                                              unlang_function_t func, unlang_function_t repeat,
+                                              unlang_function_signal_t signal, void *uctx)
+                                              CC_HINT(warn_unused_result);
+
+#ifdef __cplusplus
+}
+#endif
index 5db60e7a5c88a38f9e96bc50d0d16bbd4be2cf05..079968fbbce05b29a08b62689136514bd7e341f0 100644 (file)
@@ -27,14 +27,9 @@ RCSID("$Id$")
 #include "unlang_priv.h"
 #include "group_priv.h"
 
-unlang_action_t unlang_group(rlm_rcode_t *p_result, request_t *request)
+unlang_action_t unlang_group(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t          *stack = request->stack;
-       unlang_stack_frame_t    *frame = &stack->frame[stack->depth];
-       unlang_t                *instruction = frame->instruction;
-       unlang_group_t          *g;
-
-       g = unlang_generic_to_group(instruction);
+       unlang_group_t          *g = unlang_generic_to_group(frame->instruction);
 
        /*
         *      The compiler catches most of these, EXCEPT for the
@@ -42,7 +37,7 @@ unlang_action_t unlang_group(rlm_rcode_t *p_result, request_t *request)
         *      and can be empty.
         */
        if (!g->children) {
-               RDEBUG2("} # %s ... <ignoring empty subsection>", instruction->debug_name);
+               RDEBUG2("} # %s ... <ignoring empty subsection>", frame->instruction->debug_name);
                return UNLANG_ACTION_EXECUTE_NEXT;
        }
 
@@ -54,17 +49,14 @@ unlang_action_t unlang_group(rlm_rcode_t *p_result, request_t *request)
        return UNLANG_ACTION_PUSHED_CHILD;
 }
 
-static unlang_action_t unlang_policy(rlm_rcode_t *result, request_t *request)
+static unlang_action_t unlang_policy(rlm_rcode_t *result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t          *stack = request->stack;
-       unlang_stack_frame_t    *frame = &stack->frame[stack->depth];
-
        /*
         *      Ensure returns stop at the enclosing policy
         */
        return_point_set(frame);
 
-       return unlang_group(result, request);
+       return unlang_group(result, request, frame);
 }
 
 
index a0549fa6be35804578888d28c618fd63225d81c2..2279be11398fe6e53c1b907ae99b3d4158f75ed4 100644 (file)
@@ -29,7 +29,7 @@
 extern "C" {
 #endif
 
-unlang_action_t unlang_group(UNUSED rlm_rcode_t *p_result, request_t *request);
+unlang_action_t unlang_group(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame);
 
 #ifdef __cplusplus
 }
index dae86d677d02e73841b9039d8c5bcdb68fc68dae..6a8486b55ad92ebc9191639250bdff4afa2c5040 100644 (file)
@@ -69,11 +69,8 @@ static void instruction_dump(request_t *request, unlang_t const *instruction)
 static void frame_dump(request_t *request, unlang_stack_frame_t *frame)
 {
        instruction_dump(request, frame->instruction);
-       unlang_stack_t *stack = request->stack;
 
        RINDENT();
-
-       RDEBUG("frame           %zd", (frame - stack->frame));
        if (frame->state) RDEBUG2("state          %s (%p)", talloc_get_name(frame->state), frame->state);
        if (frame->next) {
                RDEBUG2("next           %s", frame->next->debug_name);
@@ -167,7 +164,7 @@ static inline void frame_state_init(unlang_stack_t *stack, unlang_stack_frame_t
  *     - 0 on success.
  *     - -1 on call stack too deep.
  */
-int unlang_interpret_push(request_t *request, unlang_t *instruction,
+int unlang_interpret_push(request_t *request, unlang_t const *instruction,
                          rlm_rcode_t default_rcode, bool do_next_sibling, bool top_frame)
 {
        unlang_stack_t          *stack = request->stack;
@@ -424,8 +421,8 @@ static inline void frame_pop(unlang_stack_t *stack)
  *                                     was called.
  *     - UNLANG_FRAME_ACTION_POP       the final result has been calculated for this frame.
  */
-static inline unlang_frame_action_t frame_eval(request_t *request, unlang_stack_frame_t *frame,
-                                              rlm_rcode_t *result, int *priority)
+static inline CC_HINT(always_inline)
+unlang_frame_action_t frame_eval(request_t *request, unlang_stack_frame_t *frame, rlm_rcode_t *result, int *priority)
 {
        unlang_stack_t  *stack = request->stack;
 
@@ -458,7 +455,7 @@ static inline unlang_frame_action_t frame_eval(request_t *request, unlang_stack_
                if (request->master_state == REQUEST_STOP_PROCESSING) {
                do_stop:
                        frame->result = RLM_MODULE_FAIL;
-                       frame->priority = 9999;
+                       frame->priority = MOD_PRIORITY_MAX;
 
                        RDEBUG4("** [%i] %s - STOP current subsection with (%s %d)",
                                stack->depth, __FUNCTION__,
@@ -481,7 +478,7 @@ static inline unlang_frame_action_t frame_eval(request_t *request, unlang_stack_
                        unlang_ops[instruction->type].name);
 
                fr_assert(frame->process != NULL);
-               action = frame->process(result, request);
+               action = frame->process(result, request, frame);
 
                RDEBUG4("** [%i] %s << %s (%d)", stack->depth, __FUNCTION__,
                        fr_table_str_by_value(unlang_action_table, action, "<INVALID>"), *priority);
@@ -624,7 +621,6 @@ static inline unlang_frame_action_t frame_eval(request_t *request, unlang_stack_
  */
 rlm_rcode_t unlang_interpret(request_t *request)
 {
-       int                     priority = -1;
        unlang_frame_action_t   fa = UNLANG_FRAME_ACTION_NEXT;
 
        /*
@@ -633,6 +629,8 @@ rlm_rcode_t unlang_interpret(request_t *request)
        unlang_stack_t          *stack = request->stack;
        unlang_stack_frame_t    *frame = &stack->frame[stack->depth];   /* Quiet static analysis */
 
+       stack->priority = -1;   /* Reset */
+
 #ifndef NDEBUG
        if (DEBUG_ENABLED5) DEBUG("###### unlang_interpret is starting");
        DUMP_STACK;
@@ -651,7 +649,7 @@ rlm_rcode_t unlang_interpret(request_t *request)
                        fr_assert(stack->depth < UNLANG_STACK_MAX);
 
                        frame = &stack->frame[stack->depth];
-                       fa = frame_eval(request, frame, &stack->result, &priority);
+                       fa = frame_eval(request, frame, &stack->result, &stack->priority);
 
                        /*
                         *      We were executing a frame, frame_eval()
@@ -677,7 +675,7 @@ rlm_rcode_t unlang_interpret(request_t *request)
                         *      if we had performed a module call.
                         */
                        stack->result = frame->result;
-                       priority = frame->priority;
+                       stack->priority = frame->priority;
 
                        /*
                         *      Head on back up the stack
@@ -720,7 +718,7 @@ rlm_rcode_t unlang_interpret(request_t *request)
                                }
                        }
 
-                       fa = result_calculate(request, frame, &stack->result, &priority);
+                       fa = result_calculate(request, frame, &stack->result, &stack->priority);
 
                        /*
                         *      If we're continuing after popping a frame
@@ -731,7 +729,7 @@ rlm_rcode_t unlang_interpret(request_t *request)
                                RDEBUG4("** [%i] %s - continuing after subsection with (%s %d)",
                                        stack->depth, __FUNCTION__,
                                        fr_table_str_by_value(mod_rcode_table, stack->result, "<invalid>"),
-                                       priority);
+                                       stack->priority);
                                frame_next(stack, frame);
                        /*
                         *      Else if we're really done with this frame
@@ -756,21 +754,21 @@ rlm_rcode_t unlang_interpret(request_t *request)
        /*
         *      Nothing in this section, use the top frame stack->result.
         */
-       if ((priority < 0) || (stack->result == RLM_MODULE_UNKNOWN)) {
+       if ((stack->priority < 0) || (stack->result == RLM_MODULE_UNKNOWN)) {
                        RDEBUG4("** [%i] %s - empty section, using stack result (%s %d)", stack->depth, __FUNCTION__,
-                               fr_table_str_by_value(mod_rcode_table, stack->result, "<invalid>"), priority);
+                               fr_table_str_by_value(mod_rcode_table, stack->result, "<invalid>"), stack->priority);
                stack->result = frame->result;
-               priority = frame->priority;
+               stack->priority = frame->priority;
        }
 
-       if (priority > frame->priority) {
+       if (stack->priority > frame->priority) {
                frame->result = stack->result;
-               frame->priority = priority;
+               frame->priority = stack->priority;
 
                RDEBUG4("** [%i] %s - over-riding stack->result from higher priority to (%s %d)",
                        stack->depth, __FUNCTION__,
                        fr_table_str_by_value(mod_rcode_table, stack->result, "<invalid>"),
-                       priority);
+                       stack->priority);
        }
 
        /*
@@ -779,7 +777,9 @@ rlm_rcode_t unlang_interpret(request_t *request)
         */
        RDEBUG4("** [%i] %s - interpreter exiting, returning %s", stack->depth, __FUNCTION__,
                fr_table_str_by_value(mod_rcode_table, frame->result, "<invalid>"));
+
        stack->result = frame->result;
+
        stack->depth--;
        DUMP_STACK;
 
@@ -1095,7 +1095,7 @@ static void frame_signal(request_t *request, fr_state_signal_t action, int limit
 
                if (!frame->signal) continue;
 
-               frame->signal(request, action);
+               frame->signal(request, frame, action);
        }
        stack->depth = depth;                           /* Reset */
 }
@@ -1224,7 +1224,7 @@ void unlang_interpret_mark_resumable(request_t *request)
        }
 
        if (!unlang_request_is_scheduled(request)) {
-               RDEBUG3("marking as resumable");
+               RDEBUG3("Marked as resumable");
        }
 
        fr_assert(request->backlog != NULL);
index 2fd8f3152ed6d488fa694b22b2a551ece84b14e3..eccbfccba358b0c0945c6369a65a3d5182ce2c59 100644 (file)
@@ -33,58 +33,8 @@ extern "C" {
 #define UNLANG_TOP_FRAME (true)
 #define UNLANG_SUB_FRAME (false)
 
-/** Function to call when interpreting a frame
- *
- * @param[in,out] p_result     Pointer to the current rcode, may be modified by the function.
- * @param[in] request          The current request.
- * @return an action for the interpreter to perform.
- */
-typedef unlang_action_t (*unlang_process_t)(rlm_rcode_t *p_result, request_t *request);
-
-/** Function to call if the initial function yielded and the request was signalled
- *
- * This is the operation specific cancellation function.  This function will usually
- * either call a more specialised cancellation function set when something like a module yielded,
- * or just cleanup the state of the original #unlang_process_t.
- *
- * @param[in] request          The current request.
- * @param[in] action           We're being signalled with.
- */
-typedef void (*unlang_signal_t)(request_t *request, fr_state_signal_t action);
-
-/** A generic function pushed by a module or xlat to functions deeper in the C call stack to create resumption points
- *
- * @param[in] request          The current request.
- * @param[in,out] uctx         Provided by whatever pushed the function.  Is opaque to the
- *                             interpreter, but should be usable by the function.
- *                             All input (args) and output will be done using this structure.
- * @return an #unlang_action_t.
- */
-typedef unlang_action_t (*unlang_function_t)(rlm_rcode_t *p_result, int *priority, request_t *request, void *uctx);
-
-/** An unlang operation
- *
- * These are like the opcodes in other interpreters.  Each operation, when executed
- * will return an #unlang_action_t, which determines what the interpreter does next.
- */
-typedef struct {
-       char const              *name;                          //!< Name of the operation.
-
-       unlang_process_t        interpret;                      //!< Function to interpret the keyword
-
-       unlang_signal_t         signal;                         //!< Function to signal stop / dup / whatever
-
-       bool                    debug_braces;                   //!< Whether the operation needs to print braces
-                                                               ///< in debug mode.
-
-       size_t                  frame_state_size;               //!< size of instance data in the stack frame
-
-       char const              *frame_state_name;              //!< talloc name of the frame instance data
-
-       size_t                  frame_state_pool_objects;       //!< How many sub-allocations we expect.
-
-       size_t                  frame_state_pool_size;          //!< The total size of the pool to alloc.
-} unlang_op_t;
+#define UNLANG_STACK_MAX (64)          //!< The maximum depth of the stack.
+#define UNLANG_FRAME_PRE_ALLOC (128)   //!< How much memory we pre-alloc for each frame.
 
 /** Return whether a request is currently scheduled
  *
@@ -94,10 +44,6 @@ static inline bool unlang_request_is_scheduled(request_t const *request)
        return (request->runnable_id >= 0);
 }
 
-int            unlang_interpret_push_function(request_t *request,
-                                              unlang_function_t func, unlang_function_t repeat, void *uctx)
-                                              CC_HINT(warn_unused_result);
-
 int            unlang_interpret_push_section(request_t *request, CONF_SECTION *cs,
                                              rlm_rcode_t default_action, bool top_frame)
                                              CC_HINT(warn_unused_result);
index ae03113d8cc6832f759ebb04972d5bdff789fc15..00d1075d8f55658b27190278aeb1394b415723bd 100644 (file)
 
 #define unlang_redundant_load_balance unlang_load_balance
 
-static unlang_action_t unlang_load_balance_next(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_load_balance_next(rlm_rcode_t *p_result, request_t *request,
+                                               unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_t                        *instruction = frame->instruction;
-       unlang_frame_state_redundant_t  *redundant;
-
-       unlang_group_t                  *g;
-
-       g = unlang_generic_to_group(instruction);
-
-       redundant = talloc_get_type_abort(frame->state, unlang_frame_state_redundant_t);
+       unlang_frame_state_redundant_t  *redundant = talloc_get_type_abort(frame->state, unlang_frame_state_redundant_t);
+       unlang_group_t                  *g = unlang_generic_to_group(frame->instruction);
 
 #ifdef __clang_analyzer__
        if (!redundant->found) {
@@ -74,7 +67,7 @@ static unlang_action_t unlang_load_balance_next(rlm_rcode_t *p_result, request_t
                 *      process again.
                 */
 
-               fr_assert(instruction->type != UNLANG_TYPE_LOAD_BALANCE); /* this is never called again */
+               fr_assert(frame->instruction->type != UNLANG_TYPE_LOAD_BALANCE); /* this is never called again */
 
                /*
                 *      If the current child says "return", then do
@@ -112,19 +105,14 @@ static unlang_action_t unlang_load_balance_next(rlm_rcode_t *p_result, request_t
        return UNLANG_ACTION_PUSHED_CHILD;
 }
 
-static unlang_action_t unlang_load_balance(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_load_balance(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_t                        *instruction = frame->instruction;
        unlang_frame_state_redundant_t  *redundant;
-
-       unlang_group_t                  *g;
-       unlang_load_balance_t   *gext = NULL;
+       unlang_group_t                  *g = unlang_generic_to_group(frame->instruction);
+       unlang_load_balance_t           *gext = NULL;
 
        uint32_t count = 0;
 
-       g = unlang_generic_to_group(instruction);
        if (!g->num_children) {
                *p_result = RLM_MODULE_NOOP;
                return UNLANG_ACTION_CALCULATE_RESULT;
@@ -134,7 +122,8 @@ static unlang_action_t unlang_load_balance(rlm_rcode_t *p_result, request_t *req
 
        RDEBUG4("%s setting up", frame->instruction->debug_name);
 
-       redundant = talloc_get_type_abort(frame->state, unlang_frame_state_redundant_t);
+       redundant = talloc_get_type_abort(frame->state,
+                                         unlang_frame_state_redundant_t);
 
        if (gext && gext->vpt) {
                uint32_t hash, start;
@@ -237,7 +226,7 @@ static unlang_action_t unlang_load_balance(rlm_rcode_t *p_result, request_t *req
        /*
         *      Plain "load-balance".  Just do one child.
         */
-       if (instruction->type == UNLANG_TYPE_LOAD_BALANCE) {
+       if (frame->instruction->type == UNLANG_TYPE_LOAD_BALANCE) {
                if (unlang_interpret_push(request, redundant->found,
                                          frame->result, UNLANG_NEXT_STOP, UNLANG_SUB_FRAME) < 0) {
                        *p_result = RLM_MODULE_FAIL;
@@ -254,7 +243,7 @@ static unlang_action_t unlang_load_balance(rlm_rcode_t *p_result, request_t *req
        redundant->child = NULL;
 
        frame->process = unlang_load_balance_next;
-       return unlang_load_balance_next(p_result, request);
+       return unlang_load_balance_next(p_result, request, frame);
 }
 
 void unlang_load_balance_init(void)
index ba7db59485da2bc7ca8bea816c4385cc073c5f4b..b1199745617ac6163ed98089237084f230f2a424 100644 (file)
@@ -112,19 +112,18 @@ done:
 
 /** Create a list of modifications to apply to one or more fr_pair_t lists
  *
- * @param[in] request  The current request.
  * @param[out] p_result        The rcode indicating what the result
  *                     of the operation was.
+ * @param[in] request  The current request.
+ * @param[in] frame    Current stack frame.
  * @return
  *     - UNLANG_ACTION_CALCULATE_RESULT changes were applied.
  *     - UNLANG_ACTION_PUSHED_CHILD async execution of an expansion is required.
  */
-static unlang_action_t list_mod_create(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t list_mod_create(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_frame_state_update_t     *update_state = frame->state;
-       map_t                   *map;
+       unlang_frame_state_update_t     *update_state = talloc_get_type_abort(frame->state, unlang_frame_state_update_t);
+       map_t                           *map;
 
        /*
         *      Iterate over the maps producing a set of modifications to apply.
@@ -257,20 +256,16 @@ static unlang_action_t list_mod_create(rlm_rcode_t *p_result, request_t *request
  * If one map fails in the evaluation phase, no more maps are processed, and the current
  * result is discarded.
  */
-static unlang_action_t unlang_update_state_init(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_update_state_init(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_t                        *instruction = frame->instruction;
-
-       unlang_group_t                  *g = unlang_generic_to_group(instruction);
+       unlang_group_t                  *g = unlang_generic_to_group(frame->instruction);
        unlang_map_t                    *gext = unlang_group_to_map(g);
        unlang_frame_state_update_t     *update_state;
 
        /*
         *      Initialise the frame state
         */
-       MEM(frame->state = update_state = talloc_zero_pooled_object(stack, unlang_frame_state_update_t,
+       MEM(frame->state = update_state = talloc_zero_pooled_object(request->stack, unlang_frame_state_update_t,
                                                                    (sizeof(map_t) +
                                                                    (sizeof(tmpl_t) * 2) + 128),
                                                                    g->num_children));  /* 128 is for string buffers */
@@ -285,18 +280,14 @@ static unlang_action_t unlang_update_state_init(rlm_rcode_t *p_result, request_t
         *      Call list_mod_create
         */
        frame->process = list_mod_create;
-       return list_mod_create(p_result, request);
+       return list_mod_create(p_result, request, frame);
 }
 
 
-static unlang_action_t map_proc_apply(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t map_proc_apply(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_t                        *instruction = frame->instruction;
-
-       unlang_group_t                  *g = unlang_generic_to_group(instruction);
-       unlang_map_t            *gext = unlang_group_to_map(g);
+       unlang_group_t                  *g = unlang_generic_to_group(frame->instruction);
+       unlang_map_t                    *gext = unlang_group_to_map(g);
 
        map_proc_inst_t                 *inst = gext->proc_inst;
        unlang_frame_state_map_proc_t   *map_proc_state = talloc_get_type_abort(frame->state, unlang_frame_state_map_proc_t);
@@ -317,13 +308,10 @@ static unlang_action_t map_proc_apply(rlm_rcode_t *p_result, request_t *request)
        return *p_result == RLM_MODULE_YIELD ? UNLANG_ACTION_YIELD : UNLANG_ACTION_CALCULATE_RESULT;
 }
 
-static unlang_action_t unlang_map_state_init(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_map_state_init(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_t                        *instruction = frame->instruction;
-       unlang_group_t                  *g = unlang_generic_to_group(instruction);
-       unlang_map_t            *gext = unlang_group_to_map(g);
+       unlang_group_t                  *g = unlang_generic_to_group(frame->instruction);
+       unlang_map_t                    *gext = unlang_group_to_map(g);
        map_proc_inst_t                 *inst = gext->proc_inst;
        unlang_frame_state_map_proc_t   *map_proc_state = talloc_get_type_abort(frame->state, unlang_frame_state_map_proc_t);
 
@@ -382,7 +370,7 @@ static unlang_action_t unlang_map_state_init(rlm_rcode_t *p_result, request_t *r
                goto error;
        }
 
-       return map_proc_apply(p_result, request);
+       return map_proc_apply(p_result, request, frame);
 }
 
 void unlang_map_init(void)
index f169205027122d69e565f3a1521546af7e0f373f..c1684fc1279c44f71bf95fc9578c080c7e04dd7a 100644 (file)
@@ -550,11 +550,10 @@ unlang_action_t unlang_module_yield_to_section(rlm_rcode_t *p_result,
        if (!subcs) {
                unlang_stack_t          *stack = request->stack;
                unlang_stack_frame_t    *frame = &stack->frame[stack->depth];
-               unlang_t                *instruction = frame->instruction;
-               unlang_module_t *mc;
+               unlang_module_t         *mc;
 
-               fr_assert(instruction->type == UNLANG_TYPE_MODULE);
-               mc = unlang_generic_to_module(instruction);
+               fr_assert(frame->instruction->type == UNLANG_TYPE_MODULE);
+               mc = unlang_generic_to_module(frame->instruction);
 
                /*
                 *      Be transparent to the resume function.
@@ -606,12 +605,11 @@ static inline void safe_unlock(module_instance_t *instance)
  * If there is no #unlang_module_signal_t callback defined, the action is ignored.
  *
  * @param[in] request          The current request.
+ * @param[in] frame            current stack frame.
  * @param[in] action           to signal.
  */
-static void unlang_module_signal(request_t *request, fr_state_signal_t action)
+static void unlang_module_signal(request_t *request, unlang_stack_frame_t *frame, fr_state_signal_t action)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_module_t     *state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
        unlang_module_t                 *mc = unlang_generic_to_module(frame->instruction);
 
@@ -637,10 +635,9 @@ static void unlang_module_signal(request_t *request, fr_state_signal_t action)
 /** Return UNLANG_CALCULATE_RESULT only for async async calls
  *
  */
-static unlang_action_t unlang_module_resume_final(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_module_resume_final(rlm_rcode_t *p_result, request_t *request,
+                                                 unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_module_t     *state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
 
        request->rcode = state->rcode;
@@ -653,15 +650,13 @@ static unlang_action_t unlang_module_resume_final(rlm_rcode_t *p_result, request
 /** Wrapper to call a module's resumption function
  *
  */
-static unlang_action_t unlang_module_resume(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_module_resume(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_module_t     *state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
        unlang_module_t                 *mc = unlang_generic_to_module(frame->instruction);
        char const                      *caller;
        rlm_rcode_t                     rcode = RLM_MODULE_NOOP;
-       int                             stack_depth = stack->depth;
+       int                             stack_depth = unlang_current_depth(request);
        unlang_action_t                 ua;
 
        fr_assert(state->resume != NULL);
@@ -703,8 +698,8 @@ static unlang_action_t unlang_module_resume(rlm_rcode_t *p_result, request_t *re
                fr_table_str_by_value(mod_rcode_table, rcode, "<invalid>"));
 
        if (ua == UNLANG_ACTION_YIELD) {
-               if (stack_depth < stack->depth) return UNLANG_ACTION_PUSHED_CHILD;
-               fr_assert(stack_depth == stack->depth);
+               if (stack_depth < unlang_current_depth(request)) return UNLANG_ACTION_PUSHED_CHILD;
+               fr_assert(stack_depth == unlang_current_depth(request));
                *p_result = rcode;
                return UNLANG_ACTION_YIELD;
        }
@@ -775,14 +770,11 @@ unlang_action_t unlang_module_yield(request_t *request,
        return UNLANG_ACTION_YIELD;
 }
 
-static unlang_action_t unlang_module(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_module(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
        unlang_module_t                 *mc;
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_t                        *instruction = frame->instruction;
        unlang_frame_state_module_t     *state = talloc_get_type_abort(frame->state, unlang_frame_state_module_t);
-       int                             stack_depth = stack->depth;
+       int                             stack_depth = unlang_current_depth(request);
        char const                      *caller;
        rlm_rcode_t                     rcode = RLM_MODULE_NOOP;
        unlang_action_t                 ua;
@@ -795,10 +787,10 @@ static unlang_action_t unlang_module(rlm_rcode_t *p_result, request_t *request)
         *      Process a stand-alone child, and fall through
         *      to dealing with it's parent.
         */
-       mc = unlang_generic_to_module(instruction);
+       mc = unlang_generic_to_module(frame->instruction);
        fr_assert(mc);
 
-       RDEBUG4("[%i] %s - %s (%s)", stack->depth, __FUNCTION__,
+       RDEBUG4("[%i] %s - %s (%s)", unlang_current_depth(request), __FUNCTION__,
                mc->instance->name, mc->instance->module->name);
 
        /*
@@ -849,14 +841,14 @@ static unlang_action_t unlang_module(rlm_rcode_t *p_result, request_t *request)
        /*
         *      Must be left at RDEBUG() level otherwise RDEBUG becomes pointless
         */
-       RDEBUG("%s (%s)", instruction->name ? instruction->name : "",
+       RDEBUG("%s (%s)", frame->instruction->name ? frame->instruction->name : "",
               fr_table_str_by_value(mod_rcode_table, rcode, "<invalid>"));
 
 
        if (ua == UNLANG_ACTION_YIELD) {
                state->thread->active_callers++;
-               if (stack_depth < stack->depth) return UNLANG_ACTION_PUSHED_CHILD;
-               fr_assert(stack_depth == stack->depth);
+               if (stack_depth < unlang_current_depth(request)) return UNLANG_ACTION_PUSHED_CHILD;
+               fr_assert(stack_depth == unlang_current_depth(request));
                frame->process = unlang_module_resume;
                return UNLANG_ACTION_YIELD;
        }
index bc0650c74b0ddf885a0c67111d35cf7492c166a3..262bac1bdd3fd4cb99bb63a03bd27b9d3960a300 100644 (file)
@@ -65,10 +65,10 @@ typedef struct {
        /** @} */
 } unlang_frame_state_module_t;
 
-static inline unlang_module_t *unlang_generic_to_module(unlang_t *p)
+static inline unlang_module_t *unlang_generic_to_module(unlang_t const *p)
 {
        fr_assert(p->type == UNLANG_TYPE_MODULE);
-       return talloc_get_type_abort(p, unlang_module_t);
+       return UNCONST(unlang_module_t *, talloc_get_type_abort_const(p, unlang_module_t));
 }
 
 static inline unlang_t *unlang_module_to_generic(unlang_module_t *p)
index 694d50561c311b8833220d051fe86469486b8364..f4216b9d44088f3b0faf2f15697bd8a0e62529a2 100644 (file)
@@ -66,10 +66,8 @@ static unlang_action_t unlang_parallel_child_done(UNUSED rlm_rcode_t *p_result,
 /** Run one or more sub-sections from the parallel section.
  *
  */
-static unlang_action_t unlang_parallel_process(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_parallel_process(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       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;
@@ -144,7 +142,7 @@ static unlang_action_t unlang_parallel_process(rlm_rcode_t *p_result, request_t
                         */
                        if ((unlang_interpret_push(child, NULL, RLM_MODULE_NOOP,
                                                   UNLANG_NEXT_STOP, UNLANG_TOP_FRAME) < 0) ||
-                           (unlang_interpret_push_function(child, unlang_parallel_child_done, NULL, &state->children[i]) < 0) ||
+                           (unlang_interpret_push_function(child, unlang_parallel_child_done, NULL, NULL, &state->children[i]) < 0) ||
                            (unlang_interpret_push(child,
                                                   state->children[i].instruction, RLM_MODULE_FAIL,
                                                   UNLANG_NEXT_STOP, UNLANG_SUB_FRAME) < 0)) {
@@ -265,7 +263,7 @@ static unlang_action_t unlang_parallel_process(rlm_rcode_t *p_result, request_t
                                state->priority = priority;
 
                                RDEBUG4("** [%i] %s - over-riding result from higher priority to (%s %d)",
-                                       stack->depth, __FUNCTION__,
+                                       unlang_current_depth(request), __FUNCTION__,
                                        fr_table_str_by_value(mod_rcode_table, result, "<invalid>"),
                                        priority);
                        }
@@ -376,10 +374,8 @@ static unlang_action_t unlang_parallel_process(rlm_rcode_t *p_result, request_t
 /** Send a signal from parent request to all of it's children
  *
  */
-static void unlang_parallel_signal(request_t *request, fr_state_signal_t action)
+static void unlang_parallel_signal(UNUSED request_t *request, unlang_stack_frame_t *frame, fr_state_signal_t action)
 {
-       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;
 
@@ -402,11 +398,9 @@ static void unlang_parallel_signal(request_t *request, fr_state_signal_t action)
        }
 }
 
-static unlang_action_t unlang_parallel(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_parallel(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_t                        *instruction = frame->instruction;
+       unlang_t const                  *instruction = frame->instruction;
 
        unlang_group_t                  *g;
        unlang_parallel_t               *gext;
@@ -452,7 +446,7 @@ static unlang_action_t unlang_parallel(rlm_rcode_t *p_result, request_t *request
        }
 
        frame->process = unlang_parallel_process;
-       return unlang_parallel_process(p_result, request);
+       return unlang_parallel_process(p_result, request, frame);
 }
 
 void unlang_parallel_init(void)
index 1ce4b8cc50173df8787eb0392ff397ce35fb6eae..905de8113d8f4f04646e013be76300b4ba2f8e02 100644 (file)
@@ -50,7 +50,7 @@ typedef struct {
        unlang_parallel_child_state_t   state;          //!< State of the child.
        request_t                       *child;         //!< Child request.
        char                            *name;          //!< Cache the request name.
-       unlang_t                        *instruction;   //!< broken out of g->children
+       unlang_t const                  *instruction;   //!< broken out of g->children
 } unlang_parallel_child_t;
 
 typedef struct {
index 80ee008fd3f665e4ce821ead55ca8f2ede684acd..355147a2ddfbe4f42b8922a104c0106acd186f3c 100644 (file)
@@ -27,13 +27,9 @@ RCSID("$Id$")
 #include "unlang_priv.h"
 #include "return_priv.h"
 
-unlang_action_t unlang_return(rlm_rcode_t *p_result, request_t *request)
+unlang_action_t unlang_return(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t          *stack = request->stack;
-       unlang_stack_frame_t    *frame = &stack->frame[stack->depth];
-       unlang_t                *instruction = frame->instruction;
-
-       RDEBUG2("%s", unlang_ops[instruction->type].name);
+       RDEBUG2("%s", unlang_ops[frame->instruction->type].name);
 
        *p_result = frame->result;
 
@@ -41,7 +37,7 @@ unlang_action_t unlang_return(rlm_rcode_t *p_result, request_t *request)
         *      Stop at the next return point, or if we hit
         *      the a top frame.
         */
-       return unwind_to_return(stack);
+       return unwind_to_return(request->stack);
 }
 
 void unlang_return_init(void)
index 94ea5218f791348712c3227d6f9763e8d9605b07..eaaacd592c6ffe9312a386acf3a3dfb49b025a20 100644 (file)
@@ -29,7 +29,7 @@
 extern "C" {
 #endif
 
-unlang_action_t unlang_return(UNUSED rlm_rcode_t *result, request_t *request);
+unlang_action_t unlang_return(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame);
 
 #ifdef __cplusplus
 }
index 91c6fc1f7b7db80e2b434fb54691fe28dd9adee7..0128305d58978461a2b55ad2601ee288aa8c0c5e 100644 (file)
@@ -82,10 +82,8 @@ static void unlang_max_request_time(UNUSED fr_event_list_t *el, UNUSED fr_time_t
 /** Send a signal from parent request to subrequest
  *
  */
-static void unlang_subrequest_signal(request_t *request, fr_state_signal_t action)
+static void unlang_subrequest_signal(UNUSED request_t *request, unlang_stack_frame_t *frame, fr_state_signal_t action)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_subrequest_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_subrequest_t);
        request_t                       *child = talloc_get_type_abort(state->child, request_t);
 
@@ -96,10 +94,8 @@ static void unlang_subrequest_signal(request_t *request, fr_state_signal_t actio
 /** Process a subrequest until it either detaches, or is done.
  *
  */
-static unlang_action_t unlang_subrequest_process(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_subrequest_process(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_subrequest_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_subrequest_t);
        request_t                       *child = talloc_get_type_abort(state->child, request_t);
        unlang_group_t                  *g = unlang_generic_to_group(frame->instruction);
@@ -193,10 +189,8 @@ static unlang_action_t unlang_subrequest_process(rlm_rcode_t *p_result, request_
 }
 
 
-static unlang_action_t unlang_subrequest_start(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_subrequest_start(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_subrequest_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_subrequest_t);
        request_t                       *child = state->child;
 
@@ -214,15 +208,13 @@ static unlang_action_t unlang_subrequest_start(rlm_rcode_t *p_result, request_t
        log_request_pair_list(L_DBG_LVL_1, request, NULL, &child->request_pairs, NULL);
 
        frame->process = unlang_subrequest_process;
-       return unlang_subrequest_process(p_result, request);
+       return unlang_subrequest_process(p_result, request, frame);
 }
 
 
-static unlang_action_t unlang_subrequest_state_init(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_subrequest_state_init(rlm_rcode_t *p_result, request_t *request,
+                                                   unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_t                        *instruction = frame->instruction;
        unlang_frame_state_subrequest_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_subrequest_t);
        request_t                       *child;
 
@@ -230,12 +222,12 @@ static unlang_action_t unlang_subrequest_state_init(rlm_rcode_t *p_result, reque
        fr_pair_t                       *vp;
 
        unlang_group_t                  *g;
-       unlang_subrequest_t     *gext;
+       unlang_subrequest_t             *gext;
 
        /*
         *      Initialize the state
         */
-       g = unlang_generic_to_group(instruction);
+       g = unlang_generic_to_group(frame->instruction);
        if (!g->num_children) {
                *p_result = RLM_MODULE_NOOP;
                return UNLANG_ACTION_CALCULATE_RESULT;
@@ -351,11 +343,11 @@ static unlang_action_t unlang_subrequest_state_init(rlm_rcode_t *p_result, reque
         *      keyed off the exact subrequest keyword.
         */
        state->session.enable = true;
-       state->session.unique_ptr = instruction;
+       state->session.unique_ptr = frame->instruction;
        state->session.unique_int = 0;
 
        frame->process = unlang_subrequest_start;
-       return unlang_subrequest_start(p_result, request);
+       return unlang_subrequest_start(p_result, request, frame);
 }
 
 /** Initialize a detached child
@@ -413,12 +405,10 @@ int unlang_detached_child_init(request_t *request)
        return 0;
 }
 
-static unlang_action_t unlang_detach(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_detach(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_detach_t     *state = talloc_get_type_abort(frame->state, unlang_frame_state_detach_t);
-
+       unlang_stack_frame_t            *parent_frame;
        unlang_frame_state_subrequest_t *parent_state;
 
        /*
@@ -441,8 +431,7 @@ static unlang_action_t unlang_detach(rlm_rcode_t *p_result, request_t *request)
        /*
         *      Get the PARENT's stack.
         */
-       stack = request->parent->stack;
-       frame = &stack->frame[stack->depth];
+       parent_frame = unlang_current_frame(request->parent);
        parent_state = talloc_get_type_abort(frame->state, unlang_frame_state_subrequest_t);
 
        if (!parent_state->detachable) {
@@ -464,7 +453,7 @@ static unlang_action_t unlang_detach(rlm_rcode_t *p_result, request_t *request)
         */
        fr_assert(parent_state->child == request);
        parent_state->child = NULL;
-       frame->signal = NULL;
+       parent_frame->signal = NULL;
 
        /*
         *      Pass through whatever the previous instruction had as
index 059a1f0317a4bf18164cca09188e15fe26cb7ea0..de731dfdfc5277f0cd2e9d7c52b01e3fde60bf21 100644 (file)
@@ -30,11 +30,8 @@ RCSID("$Id$")
 #include "switch_priv.h"
 #include "unlang_priv.h"
 
-static unlang_action_t unlang_switch(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_switch(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t          *stack = request->stack;
-       unlang_stack_frame_t    *frame = &stack->frame[stack->depth];
-       unlang_t                *instruction = frame->instruction;
        unlang_t                *this, *found, *null_case;
 
        unlang_group_t          *switch_g;
@@ -44,7 +41,7 @@ static unlang_action_t unlang_switch(rlm_rcode_t *p_result, request_t *request)
        map_t                   map;
        tmpl_t                  vpt, *switch_vpt;
 
-       switch_g = unlang_generic_to_group(instruction);
+       switch_g = unlang_generic_to_group(frame->instruction);
        switch_gext = unlang_group_to_switch(switch_g);
 
        memset(&cond, 0, sizeof(cond));
@@ -176,21 +173,16 @@ do_null_case:
 }
 
 
-static unlang_action_t unlang_case(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_case(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t          *stack = request->stack;
-       unlang_stack_frame_t    *frame = &stack->frame[stack->depth];
-       unlang_t                *instruction = frame->instruction;
-       unlang_group_t          *g;
-
-       g = unlang_generic_to_group(instruction);
+       unlang_group_t          *g = unlang_generic_to_group(frame->instruction);
 
        if (!g->children) {
                *p_result = RLM_MODULE_NOOP;
                return UNLANG_ACTION_CALCULATE_RESULT;
        }
 
-       return unlang_group(p_result, request);
+       return unlang_group(p_result, request, frame);
 }
 
 void unlang_switch_init(void)
index 12b48f91fa9820083598ccd14aef0bbc62a050db..9fdc8e520dfe2fa0bbcfe517a75918e6dd874fa8 100644 (file)
@@ -76,12 +76,11 @@ static void unlang_tmpl_exec_cleanup(request_t *request)
  * If there is no #fr_unlang_tmpl_signal_t callback defined, the action is ignored.
  *
  * @param[in] request          The current request.
+ * @param[in] frame            being signalled.
  * @param[in] action           to signal.
  */
-static void unlang_tmpl_signal(request_t *request, fr_state_signal_t action)
+static void unlang_tmpl_signal(request_t *request, unlang_stack_frame_t *frame, fr_state_signal_t action)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_tmpl_t       *state = talloc_get_type_abort(frame->state,
                                                                       unlang_frame_state_tmpl_t);
 
@@ -298,12 +297,9 @@ static void unlang_tmpl_exec_timeout(
  *  called repeatedly until the resumption function returns a final
  *  value.
  */
-static unlang_action_t unlang_tmpl_resume(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_tmpl_resume(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_frame_state_tmpl_t       *state = talloc_get_type_abort(frame->state,
-                                                                      unlang_frame_state_tmpl_t);
+       unlang_frame_state_tmpl_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_tmpl_t);
 
        if (state->out) fr_dlist_move(state->out, &state->box);
 
@@ -325,10 +321,9 @@ static unlang_action_t unlang_tmpl_resume(rlm_rcode_t *p_result, request_t *requ
 /** Wrapper to call exec after the program has finished executing
  *
  */
-static unlang_action_t unlang_tmpl_exec_wait_final(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_tmpl_exec_wait_final(rlm_rcode_t *p_result, request_t *request,
+                                                  unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_tmpl_t       *state = talloc_get_type_abort(frame->state,
                                                                       unlang_frame_state_tmpl_t);
 
@@ -411,19 +406,17 @@ static unlang_action_t unlang_tmpl_exec_wait_final(rlm_rcode_t *p_result, reques
         */
 resume:
        frame->process = unlang_tmpl_resume;
-       return unlang_tmpl_resume(p_result, request);
+       return unlang_tmpl_resume(p_result, request, frame);
 }
 
 
 /** Wrapper to call exec after a tmpl has been expanded
  *
  */
-static unlang_action_t unlang_tmpl_exec_wait_resume(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_tmpl_exec_wait_resume(rlm_rcode_t *p_result, request_t *request,
+                                                   unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_frame_state_tmpl_t       *state = talloc_get_type_abort(frame->state,
-                                                                      unlang_frame_state_tmpl_t);
+       unlang_frame_state_tmpl_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_tmpl_t);
        pid_t                           pid;
        int                             *fd_p = NULL;
 
@@ -490,12 +483,10 @@ static unlang_action_t unlang_tmpl_exec_wait_resume(rlm_rcode_t *p_result, reque
 /** Wrapper to call exec after a tmpl has been expanded
  *
  */
-static unlang_action_t unlang_tmpl_exec_nowait_resume(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_tmpl_exec_nowait_resume(rlm_rcode_t *p_result, request_t *request,
+                                                     unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_frame_state_tmpl_t       *state = talloc_get_type_abort(frame->state,
-                                                                      unlang_frame_state_tmpl_t);
+       unlang_frame_state_tmpl_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_tmpl_t);
 
        if (fr_exec_nowait(request, &state->box, state->vps) < 0) {
                RPEDEBUG("Failed executing program");
@@ -514,12 +505,9 @@ static unlang_action_t unlang_tmpl_exec_nowait_resume(rlm_rcode_t *p_result, req
 }
 
 
-static unlang_action_t unlang_tmpl(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_tmpl(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
-       unlang_frame_state_tmpl_t       *state = talloc_get_type_abort(frame->state,
-                                                                      unlang_frame_state_tmpl_t);
+       unlang_frame_state_tmpl_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_tmpl_t);
        unlang_tmpl_t                   *ut = unlang_generic_to_tmpl(frame->instruction);
        xlat_exp_t const                *xlat;
 
index 72a2f8e363c67a2592b6370efe2c1f35b4bf948d..f61d69a48a281f64b75bd6ad51478c769ab38e31 100644 (file)
@@ -100,6 +100,7 @@ typedef enum {
 #define UNLANG_NORMAL_CHILD    (false)
 
 typedef struct unlang_s unlang_t;
+typedef struct unlang_stack_frame_s unlang_stack_frame_t;
 
 /** A node in a graph of #unlang_op_t (s) that we execute
  *
@@ -157,6 +158,55 @@ typedef struct {
        xlat_flags_t            flags;
 } unlang_tmpl_t;
 
+/** Function to call when interpreting a frame
+ *
+ * @param[in,out] p_result     Pointer to the current rcode, may be modified by the function.
+ * @param[in] request          The current request.
+ * @param[in] frame            being executed.
+ *
+ * @return an action for the interpreter to perform.
+ */
+typedef unlang_action_t (*unlang_process_t)(rlm_rcode_t *p_result, request_t *request,
+                                           unlang_stack_frame_t *frame);
+
+/** Function to call if the request was signalled
+ *
+ * This is the instruction specific cancellation function.
+ * This function will usually either call a more specialised cancellation function
+ * set when something like a module yielded, or just cleanup the state of the original
+ * #unlang_process_t.
+ *
+ * @param[in] request          The current request.
+ * @param[in] frame            being signalled.
+ * @param[in] action           We're being signalled with.
+ */
+typedef void (*unlang_signal_t)(request_t *request,
+                               unlang_stack_frame_t *frame, fr_state_signal_t action);
+
+/** An unlang operation
+ *
+ * These are like the opcodes in other interpreters.  Each operation, when executed
+ * will return an #unlang_action_t, which determines what the interpreter does next.
+ */
+typedef struct {
+       char const              *name;                          //!< Name of the operation.
+
+       unlang_process_t        interpret;                      //!< Function to interpret the keyword
+
+       unlang_signal_t         signal;                         //!< Function to signal stop / dup / whatever
+
+       bool                    debug_braces;                   //!< Whether the operation needs to print braces
+                                                               ///< in debug mode.
+
+       size_t                  frame_state_size;               //!< size of instance data in the stack frame
+
+       char const              *frame_state_name;              //!< talloc name of the frame instance data
+
+       size_t                  frame_state_pool_objects;       //!< How many sub-allocations we expect.
+
+       size_t                  frame_state_pool_size;          //!< The total size of the pool to alloc.
+} unlang_op_t;
+
 /** Our interpreter stack, as distinct from the C stack
  *
  * We don't call the modules recursively.  Instead we iterate over a list of #unlang_t and
@@ -169,9 +219,9 @@ typedef struct {
  * through the server.  Because the interpreter stack is distinct from the C stack, we can have
  * a single system thread with many thousands of pending requests.
  */
-typedef struct {
-       unlang_t                *instruction;                   //!< The unlang node we're evaluating.
-       unlang_t                *next;                          //!< The next unlang node we will evaluate
+struct unlang_stack_frame_s {
+       unlang_t const          *instruction;                   //!< The unlang node we're evaluating.
+       unlang_t const          *next;                          //!< The next unlang node we will evaluate
 
        unlang_process_t        process;                        //!< function to call for interpreting this stack frame
        unlang_signal_t         signal;                         //!< function to call when signalling this stack frame
@@ -187,19 +237,20 @@ typedef struct {
         */
        void                    *state;
 
-       rlm_rcode_t             result;                         //!< The result from executing the instruction.
+       rlm_rcode_t             result;                         //!< The result from executing the instruction.
        int                     priority;                       //!< Result priority.  When we pop this stack frame
                                                                ///< this priority will be compared with the one of the
                                                                ///< frame lower in the stack to determine if the
                                                                ///< result stored in the lower stack frame should
                                                                ///< be replaced.
        uint8_t                 uflags;                         //!< Unwind markers
-} unlang_stack_frame_t;
+};
 
 /** An unlang stack associated with a request
  *
  */
 typedef struct {
+       int                     priority;                       //!< Current priority.
        rlm_rcode_t             result;                         //!< The current stack rcode.
        int                     depth;                          //!< Current depth we're executing at.
        uint8_t                 unwind;                         //!< Unwind to this frame if it exists.
@@ -228,13 +279,13 @@ static inline void repeatable_clear(unlang_stack_frame_t *frame)  { frame->uflags
 static inline void top_frame_clear(unlang_stack_frame_t *frame)                { frame->uflags &= ~UNWIND_FLAG_TOP_FRAME; }
 static inline void break_point_clear(unlang_stack_frame_t *frame)      { frame->uflags &= ~UNWIND_FLAG_BREAK_POINT; }
 static inline void return_point_clear(unlang_stack_frame_t *frame)     { frame->uflags &= ~UNWIND_FLAG_RETURN_POINT; }
-static inline void yielded_clear(unlang_stack_frame_t *frame)  { frame->uflags &= ~UNWIND_FLAG_YIELDED; }
+static inline void yielded_clear(unlang_stack_frame_t *frame)          { frame->uflags &= ~UNWIND_FLAG_YIELDED; }
 
-static inline bool is_repeatable(unlang_stack_frame_t *frame)          { return frame->uflags & UNWIND_FLAG_REPEAT; }
-static inline bool is_top_frame(unlang_stack_frame_t *frame)           { return frame->uflags & UNWIND_FLAG_TOP_FRAME; }
-static inline bool is_break_point(unlang_stack_frame_t *frame)         { return frame->uflags & UNWIND_FLAG_BREAK_POINT; }
-static inline bool is_return_point(unlang_stack_frame_t *frame)        { return frame->uflags & UNWIND_FLAG_RETURN_POINT; }
-static inline bool is_yielded(unlang_stack_frame_t *frame)             { return frame->uflags & UNWIND_FLAG_YIELDED; }
+static inline bool is_repeatable(unlang_stack_frame_t const *frame)    { return frame->uflags & UNWIND_FLAG_REPEAT; }
+static inline bool is_top_frame(unlang_stack_frame_t const *frame)     { return frame->uflags & UNWIND_FLAG_TOP_FRAME; }
+static inline bool is_break_point(unlang_stack_frame_t const *frame)   { return frame->uflags & UNWIND_FLAG_BREAK_POINT; }
+static inline bool is_return_point(unlang_stack_frame_t const *frame)  { return frame->uflags & UNWIND_FLAG_RETURN_POINT; }
+static inline bool is_yielded(unlang_stack_frame_t const *frame)       { return frame->uflags & UNWIND_FLAG_YIELDED; }
 
 static inline unlang_action_t unwind_to_break(unlang_stack_t *stack)
 {
@@ -252,6 +303,20 @@ static inline unlang_action_t unwind_all(unlang_stack_t *stack)
        return UNLANG_ACTION_UNWIND;
 }
 
+static inline unlang_stack_frame_t *unlang_current_frame(request_t *request)
+{
+       unlang_stack_t *stack = request->stack;
+
+       return &stack->frame[stack->depth];
+}
+
+static inline int unlang_current_depth(request_t *request)
+{
+       unlang_stack_t *stack = request->stack;
+
+       return stack->depth;
+}
+
 /** Different operations the interpreter can execute
  */
 extern unlang_op_t unlang_ops[];
@@ -268,27 +333,27 @@ extern size_t mod_rcode_table_len;
  *
  * @{
  */
-static inline unlang_group_t *unlang_generic_to_group(unlang_t *p)
+static inline unlang_group_t *unlang_generic_to_group(unlang_t const *p)
 {
        fr_assert((p->type > UNLANG_TYPE_MODULE) && (p->type <= UNLANG_TYPE_POLICY));
 
-       return (unlang_group_t *)p;
+       return UNCONST(unlang_group_t *, p);
 }
 
-static inline unlang_t *unlang_group_to_generic(unlang_group_t *p)
+static inline unlang_t *unlang_group_to_generic(unlang_group_t const *p)
 {
-       return (unlang_t *)p;
+       return UNCONST(unlang_t *, p);
 }
 
-static inline unlang_tmpl_t *unlang_generic_to_tmpl(unlang_t *p)
+static inline unlang_tmpl_t *unlang_generic_to_tmpl(unlang_t const *p)
 {
        fr_assert(p->type == UNLANG_TYPE_TMPL);
-       return talloc_get_type_abort(p, unlang_tmpl_t);
+       return UNCONST(unlang_tmpl_t *, talloc_get_type_abort_const(p, unlang_tmpl_t));
 }
 
-static inline unlang_t *unlang_tmpl_to_generic(unlang_tmpl_t *p)
+static inline unlang_t *unlang_tmpl_to_generic(unlang_tmpl_t const *p)
 {
-       return (unlang_t *)p;
+       return UNCONST(unlang_t *, p);
 }
 /** @} */
 
@@ -296,7 +361,7 @@ static inline unlang_t *unlang_tmpl_to_generic(unlang_tmpl_t *p)
  *
  * @{
  */
-int            unlang_interpret_push(request_t *request, unlang_t *instruction,
+int            unlang_interpret_push(request_t *request, unlang_t const *instruction,
                                      rlm_rcode_t default_rcode, bool do_next_sibling, bool top_frame)
                                      CC_HINT(warn_unused_result);
 
@@ -324,6 +389,8 @@ request_t           *unlang_io_subrequest_alloc(request_t *parent, fr_dict_t const *names
  *
  * @{
  */
+void           unlang_register(int type, unlang_op_t *op);
+
 void           unlang_call_init(void);
 
 void           unlang_caller_init(void);
index 94be17fa4c36c3c85a94a0196022e2e761815cba..73493e8fffbced7725f53facb0b5127c104dd4c7 100644 (file)
@@ -227,10 +227,8 @@ int unlang_xlat_push(TALLOC_CTX *ctx, fr_value_box_list_t *out,
  * Calls the xlat interpreter and translates its wants and needs into
  * unlang_action_t codes.
  */
-static unlang_action_t unlang_xlat(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_xlat(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_xlat_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_xlat_t);
        xlat_exp_t const                *child = NULL;
        xlat_action_t                   xa;
@@ -290,12 +288,11 @@ static unlang_action_t unlang_xlat(rlm_rcode_t *p_result, request_t *request)
  * If there is no #xlat_func_signal_t callback defined, the action is ignored.
  *
  * @param[in] request          The current request.
+ * @param[in] frame            The current stack frame.
  * @param[in] action           What the request should do (the type of signal).
  */
-static void unlang_xlat_signal(request_t *request, fr_state_signal_t action)
+static void unlang_xlat_signal(request_t *request, unlang_stack_frame_t *frame, fr_state_signal_t action)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_xlat_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_xlat_t);
 
        /*
@@ -318,14 +315,13 @@ static void unlang_xlat_signal(request_t *request, fr_state_signal_t action)
  *                       - RLM_MODULE_YIELD if additional asynchronous
  *                         operations need to be performed.
  * @param[in] request  to resume processing.
+ * @param[in] frame    the current stack frame.
  * @return
  *     - UNLANG_ACTION_YIELD   if yielding.
  *     - UNLANG_ACTION_CALCULATE_RESULT if done.
  */
-static unlang_action_t unlang_xlat_resume(rlm_rcode_t *p_result, request_t *request)
+static unlang_action_t unlang_xlat_resume(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
 {
-       unlang_stack_t                  *stack = request->stack;
-       unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_frame_state_xlat_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_xlat_t);
        xlat_action_t                   xa;
 
index be0cb8e36c8821182a8090d33789e25a864ca306..82c981a20585a038cebb4271954a2bd57fc9b597 100644 (file)
@@ -176,7 +176,7 @@ static unlang_action_t eap_tls_virtual_server(rlm_rcode_t *p_result, rlm_eap_tls
        /*
         *      Catch the interpreter on the way back up the stack
         */
-       if (unlang_interpret_push_function(request, NULL, eap_tls_virtual_server_result, eap_session) < 0) {
+       if (unlang_interpret_push_function(request, NULL, eap_tls_virtual_server_result, NULL, eap_session) < 0) {
                RETURN_MODULE_FAIL;
        }