]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add UNLANG_TYPE_CALL to the parser
authorAlan T. DeKok <aland@freeradius.org>
Thu, 14 Sep 2017 16:53:23 +0000 (12:53 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 14 Sep 2017 23:30:31 +0000 (19:30 -0400)
and bare-bones interpreter

src/include/interpreter.h
src/main/unlang_compile.c
src/main/unlang_interpret.c

index ebe0d6b07512613d99bce2c7d574bfe15a1c02da..006162700f32de17466189649d35b40b5732a917 100644 (file)
@@ -69,6 +69,7 @@ typedef enum {
                                                //!< values from a #map_proc_t call).
        UNLANG_TYPE_SUBREQUEST,                 //!< create a child subrequest
        UNLANG_TYPE_DETACH,                     //!< detach a child
+       UNLANG_TYPE_CALL,                       //!< call another virtual server
 #endif
        UNLANG_TYPE_POLICY,                     //!< Policy section.
        UNLANG_TYPE_XLAT_INLINE,                //!< xlat statement, inline in "unlang"
index b4d7730825a6fb2a612436d12ee6841cf575eb5b..d0461b24fef2ceab7a52106256d7a93bcd26e5b0 100644 (file)
@@ -2556,6 +2556,66 @@ static unlang_t *compile_subrequest(unlang_t *parent, unlang_compile_t *unlang_c
 }
 
 
+static unlang_t *compile_call(unlang_t *parent, unlang_compile_t *unlang_ctx, CONF_SECTION *cs,
+                                   unlang_group_type_t group_type, unlang_group_type_t parentgroup_type, unlang_type_t mod_type)
+{
+       ssize_t slen;
+       char const *name2;
+       unlang_group_t *g;
+       unlang_t *c;
+       FR_TOKEN type;
+
+       name2 = cf_section_name2(cs);
+       if (!name2) {
+               cf_log_err(cs, "'call' must be given with a server.PACKET argument");
+               return NULL;
+       }
+
+       type = cf_section_name2_quote(cs);
+       if (type != T_BARE_WORD) {
+               cf_log_err(cs, "The arguments to 'call' cannot by a quoted string or a dynamic value");
+               return NULL;
+       }
+
+       g = group_allocate(parent, cs, group_type, mod_type);
+       if (!g) return NULL;
+
+       slen = tmpl_afrom_str(g, &g->vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
+       if (slen < 0) {
+               char *spaces, *text;
+
+               fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror());
+
+               cf_log_err(cs, "Syntax error");
+               cf_log_err(cs, "%s", name2);
+               cf_log_err(cs, "%s^ %s", spaces, text);
+
+               talloc_free(g);
+               talloc_free(spaces);
+               talloc_free(text);
+
+               return NULL;
+       }
+
+       /*
+        *      Convert TMPL_TYPE_UNPARSED (it might have been
+        *      an attribute) to TMPL_TYPE_DATA, with
+        *      FR_TYPE_STRING data.
+        */
+       tmpl_cast_in_place_str(g->vpt);
+
+       /*
+        *      @todo - look up server && packet type
+        */
+
+       c = unlang_group_to_generic(g);
+       c->name = unlang_ops[c->type].name;
+       c->debug_name = c->name;
+
+       return compile_children(g, parent, unlang_ctx, group_type, parentgroup_type);
+}
+
+
 /** Load a named module from "instantiate" or "policy".
  *
  * If it's "foo.method", look for "foo", and return "method" as the method
@@ -2718,6 +2778,7 @@ static modcall_compile_t compile_table[] = {
        { "switch",             compile_switch, UNLANG_GROUP_TYPE_SIMPLE, UNLANG_TYPE_SWITCH, REQUIRE_CHILDREN },
        { "parallel",           compile_parallel, UNLANG_GROUP_TYPE_SIMPLE, UNLANG_TYPE_PARALLEL, REQUIRE_CHILDREN },
        { "subrequest",         compile_subrequest, UNLANG_GROUP_TYPE_SIMPLE, UNLANG_TYPE_SUBREQUEST, REQUIRE_CHILDREN },
+       { "call",               compile_call, UNLANG_GROUP_TYPE_SIMPLE, UNLANG_TYPE_CALL, ALLOW_EMPTY_GROUP },
 
        { NULL, NULL, 0, UNLANG_TYPE_NULL }
 };
index f4eac42c21ae34798b2ad1555cb12957a88028e8..65b1896a38cb3ce7d6b894ef1bfafb1186201174 100644 (file)
@@ -707,6 +707,25 @@ static unlang_action_t unlang_detach(REQUEST *request, unlang_stack_t *stack,
        return UNLANG_ACTION_CALCULATE_RESULT;
 }
 
+static unlang_action_t unlang_call(REQUEST *request, unlang_stack_t *stack,
+                                  UNUSED rlm_rcode_t *presult, UNUSED int *priority)
+{
+       unlang_stack_frame_t    *frame = &stack->frame[stack->depth];
+       unlang_t                *instruction = frame->instruction;
+       unlang_group_t          *g;
+
+       g = unlang_generic_to_group(instruction);
+       rad_assert(g->children != NULL);
+
+       rad_assert(request->async->process == unlang_process_continue);
+
+       RDEBUG("FAKING CALL TO %s", g->vpt->name);
+
+       unlang_push(stack, g->children, frame->result, UNLANG_NEXT_CONTINUE, UNLANG_SUB_FRAME);
+       return UNLANG_ACTION_PUSHED_CHILD;
+}
+
+
 static unlang_action_t unlang_subrequest(REQUEST *request, unlang_stack_t *stack,
                                         rlm_rcode_t *presult, int *priority)
 {
@@ -1796,6 +1815,11 @@ unlang_op_t unlang_ops[] = {
                .func = unlang_detach,
                .debug_braces = false
        },
+       [UNLANG_TYPE_CALL] = {
+               .name = "call",
+               .func = unlang_call,
+               .debug_braces = true
+       },
 #endif
        [UNLANG_TYPE_XLAT_INLINE] = {
                .name = "xlat_inline",