vp_tmpl_rules_t const *rules;
} unlang_compile_t;
+static unlang_t *compile_empty(unlang_t *parent, unlang_compile_t *unlang_ctx, CONF_SECTION *cs,
+ unlang_type_t mod_type, fr_cond_type_t cond_type);
+
static char const modcall_spaces[] = " ";
}
}
+ if (!cf_item_next(cs, NULL)) {
+ talloc_free(vpt);
+ return compile_empty(parent, unlang_ctx, cs, UNLANG_TYPE_MAP, COND_TYPE_INVALID);
+ }
+
/*
* This looks at cs->name2 to determine which list to update
*/
vp_tmpl_rules_t parse_rules;
+ if (!cf_item_next(cs, NULL)) {
+ return compile_empty(parent, unlang_ctx, cs, UNLANG_TYPE_UPDATE, COND_TYPE_INVALID);
+ }
+
/*
* We allow unknown attributes here.
*/
c = unlang_group_to_generic(g);
if (name2) {
- c->name = name2;
+ c->name = talloc_typed_strdup(c, name2);
c->debug_name = talloc_typed_asprintf(c, "update %s", name2);
} else {
- c->name = unlang_ops[c->type].name;
- c->debug_name = unlang_ops[c->type].name;
+ c->name = talloc_typed_strdup(c, unlang_ops[c->type].name);
+ c->debug_name = talloc_typed_strdup(c, unlang_ops[c->type].name);
}
(void) compile_action_defaults(c, unlang_ctx);
vp_tmpl_rules_t parse_rules;
+ if (!cf_item_next(cs, NULL)) {
+ return compile_empty(parent, unlang_ctx, cs, UNLANG_TYPE_FILTER, COND_TYPE_INVALID);
+ }
+
/*
* We allow unknown attributes here.
*/
c = unlang_group_to_generic(g);
if (name2) {
- c->name = name2;
+ c->name = talloc_typed_strdup(c, name2);
c->debug_name = talloc_typed_asprintf(c, "filter %s", name2);
} else {
- c->name = unlang_ops[c->type].name;
- c->debug_name = unlang_ops[c->type].name;
+ c->name = talloc_typed_strdup(c, unlang_ops[c->type].name);
+ c->debug_name = talloc_typed_strdup(c, unlang_ops[c->type].name);
}
(void) compile_action_defaults(c, unlang_ctx);
unlang_group_t *g;
unlang_t *c;
- g = group_allocate(parent, cs, mod_type);
+ /*
+ * If we're compiling an empty section, then the
+ * *intepreter* type is GROUP, even if the *debug names*
+ * are something else.
+ */
+ g = group_allocate(parent, cs, UNLANG_TYPE_GROUP);
if (!g) return NULL;
c = unlang_group_to_generic(g);
if (!cs) {
- c->name = unlang_ops[c->type].name;
+ c->name = talloc_typed_strdup(c, unlang_ops[mod_type].name);
c->debug_name = c->name;
} else {
name2 = cf_section_name2(cs);
if (!name2) {
- c->name = cf_section_name1(cs);
+ c->name = talloc_typed_strdup(c, cf_section_name1(cs));
c->debug_name = c->name;
} else {
- c->name = name2;
- c->debug_name = talloc_typed_asprintf(c, "%s %s", unlang_ops[c->type].name, name2);
+ c->name = talloc_typed_strdup(c, name2);
+ c->debug_name = talloc_typed_asprintf(c, "%s %s", unlang_ops[mod_type].name, name2);
}
}
unlang_group_t *g;
unlang_t *c;
+ if (!cf_item_next(cs, NULL)) {
+ return compile_empty(parent, unlang_ctx, cs, mod_type, COND_TYPE_INVALID);
+ }
+
g = group_allocate(parent, cs, mod_type);
if (!g) return NULL;
return NULL;
}
+ if (!cf_item_next(cs, NULL)) {
+ return compile_empty(parent, unlang_ctx, cs, UNLANG_TYPE_SWITCH, COND_TYPE_INVALID);
+ }
+
g = group_allocate(parent, cs, UNLANG_TYPE_SWITCH);
if (!g) return NULL;
}
c = unlang_group_to_generic(g);
- c->name = unlang_ops[c->type].name;
+ c->name = talloc_typed_strdup(c, unlang_ops[c->type].name);
c->debug_name = talloc_typed_asprintf(c, "%s %s", unlang_ops[c->type].name, cf_section_name2(cs));
/*
}
} /* else it's a default 'case' statement */
+ if (!cf_item_next(cs, NULL)) {
+ talloc_free(vpt);
+ return compile_empty(parent, unlang_ctx, cs, UNLANG_TYPE_CASE, COND_TYPE_INVALID);
+ }
+
c = compile_section(parent, unlang_ctx, cs, UNLANG_TYPE_CASE);
if (!c) {
talloc_free(vpt);
* default case. compile_section sets it to name2,
* unless name2 is NULL, in which case it sets it to name1.
*/
- c->name = name2;
+ c->name = talloc_typed_strdup(c, name2);
if (!name2) {
- c->debug_name = unlang_ops[c->type].name;
+ c->debug_name = talloc_typed_strdup(c, unlang_ops[c->type].name);
} else {
c->debug_name = talloc_typed_asprintf(c, "%s %s", unlang_ops[c->type].name, name2);
}
return NULL;
}
+ if (!cf_item_next(cs, NULL)) {
+ talloc_free(vpt);
+ return compile_empty(parent, unlang_ctx, cs, UNLANG_TYPE_FOREACH, COND_TYPE_INVALID);
+ }
+
/*
* If we don't have a negative return code, we must have a vpt
* (mostly to quiet coverity).
return NULL;
}
- c->name = unlang_ops[c->type].name;
+ c->name = talloc_typed_strdup(c, unlang_ops[c->type].name);
c->debug_name = talloc_typed_asprintf(c, "%s %s", unlang_ops[c->type].name, name2);
g = unlang_generic_to_group(c);
c = unlang_xlat_inline_to_generic(mx);
c->parent = parent;
c->next = NULL;
- c->name = "expand";
+ c->name = talloc_typed_strdup(c, "expand");
c->debug_name = c->name;
c->type = UNLANG_TYPE_XLAT_INLINE;
c = compile_section(parent, unlang_ctx, cs, mod_type);
if (!c) return NULL;
- c->name = unlang_ops[c->type].name;
+ c->name = talloc_typed_strdup(c, unlang_ops[c->type].name);
c->debug_name = talloc_typed_asprintf(c, "%s %s", unlang_ops[c->type].name, cf_section_name2(cs));
g = unlang_generic_to_group(c);
if (!c) return c;
- c->name = unlang_ops[c->type].name;
+ c->name = talloc_typed_strdup(c, unlang_ops[c->type].name);
c->debug_name = c->name;
return c;
char const *name2;
unlang_t *c;
- /*
- * No children? Die!
- */
- if (!cf_item_next(cs, NULL)) {
- cf_log_err(cs, "'redundant' sections cannot be empty");
- return NULL;
- }
-
if (!all_children_are_modules(cs, cf_section_name1(cs))) {
return NULL;
}
return NULL;
}
+ c->name = talloc_typed_strdup(c, unlang_ops[c->type].name);
c->debug_name = c->name;
- c->name = unlang_ops[c->type].name;
return c;
}
}
} else {
- c->debug_name = c->name;
+ c->debug_name = talloc_typed_strdup(c, unlang_ops[c->type].name);
}
- c->name = unlang_ops[c->type].name;
+ c->name = talloc_typed_strdup(c, unlang_ops[c->type].name);
return c;
}
bool clone = true;
bool detach = false;
- /*
- * No children? Die!
- */
- if (!cf_item_next(cs, NULL)) {
- cf_log_err(cs, "parallel sections cannot be empty");
- return NULL;
- }
-
/*
* Parallel sections can create empty children, if the
* admin demands it. Otherwise, the principle of least
g->clone = clone;
g->detach = detach;
- c->name = c->debug_name = unlang_ops[c->type].name;
+ c->name = talloc_typed_strdup(c, unlang_ops[c->type].name);
+ c->debug_name = c->name;
return c;
}
char buffer2[64];
char buffer3[64];
- g = group_allocate(parent, cs, UNLANG_TYPE_SUBREQUEST);
- if (!g) return NULL;
-
- c = unlang_group_to_generic(g);
- c->name = unlang_ops[c->type].name;
- c->debug_name = c->name;
-
/*
* subrequests can specify the dictionary if they want to.
*/
parse_rules = *unlang_ctx->rules;
parse_rules.dict_def = dict;
+ if (!cf_item_next(cs, NULL)) {
+ return compile_empty(parent, unlang_ctx, cs, UNLANG_TYPE_SUBREQUEST, COND_TYPE_INVALID);
+ }
+
+ g = group_allocate(parent, cs, UNLANG_TYPE_SUBREQUEST);
+ if (!g) return NULL;
+
+ c = unlang_group_to_generic(g);
+ c->name = talloc_typed_strdup(c, unlang_ops[c->type].name);
+ c->debug_name = c->name;
+
unlang_ctx2.actions = unlang_ctx->actions;
/*
return NULL;
}
- g = group_allocate(parent, cs, UNLANG_TYPE_CALL);
- if (!g) return NULL;
-
server_cs = virtual_server_find(server);
if (!server_cs) {
cf_log_err(cs, "Unknown virtual server '%s'", server);
- talloc_free(g);
return NULL;
}
unlang_ctx->rules->dict_def && (unlang_ctx->rules->dict_def != dict)) {
cf_log_err(cs, "Cannot call namespace '%s' from namespaces '%s'",
fr_dict_root(dict)->name, fr_dict_root(unlang_ctx->rules->dict_def)->name);
- talloc_free(g);
return NULL;
}
+ if (!cf_item_next(cs, NULL)) {
+ return compile_empty(parent, unlang_ctx, cs, UNLANG_TYPE_CALL, COND_TYPE_INVALID);
+ }
+
+ g = group_allocate(parent, cs, UNLANG_TYPE_CALL);
+ if (!g) return NULL;
+
g->server_cs = server_cs;
c = unlang_group_to_generic(g);
- c->name = unlang_ops[c->type].name;
+ c->name = talloc_typed_strdup(c, unlang_ops[c->type].name);
c->debug_name = talloc_typed_asprintf(c, "%s %s", c->name, server);
return compile_children(g, parent, unlang_ctx);
(void) compile_action_defaults(c, unlang_ctx);
- c->name = realname;
- c->debug_name = realname;
+ c->name = talloc_typed_strdup(c, realname);
+ c->debug_name = c->name;
c->type = UNLANG_TYPE_MODULE;
if (!compile_action_section(c, ci)) {
typedef struct {
char const *name;
modcall_compile_function_t compile;
- bool require_children;
} modcall_compile_t;
-#define ALLOW_EMPTY_GROUP (false)
-#define REQUIRE_CHILDREN (true)
-
static modcall_compile_t compile_table[] = {
- { "group", compile_group, REQUIRE_CHILDREN },
- { "redundant", compile_redundant, REQUIRE_CHILDREN },
- { "load-balance", compile_load_balance, REQUIRE_CHILDREN },
- { "redundant-load-balance", compile_redundant_load_balance, REQUIRE_CHILDREN },
-
- { "case", compile_case, ALLOW_EMPTY_GROUP },
- { "foreach", compile_foreach, REQUIRE_CHILDREN },
- { "if", compile_if, ALLOW_EMPTY_GROUP },
- { "elsif", compile_elsif, ALLOW_EMPTY_GROUP },
- { "else", compile_else, REQUIRE_CHILDREN },
- { "filter", compile_filter, REQUIRE_CHILDREN },
- { "update", compile_update, REQUIRE_CHILDREN },
- { "map", compile_map, REQUIRE_CHILDREN },
- { "switch", compile_switch, REQUIRE_CHILDREN },
- { "parallel", compile_parallel, REQUIRE_CHILDREN },
- { "subrequest", compile_subrequest, REQUIRE_CHILDREN },
- { "call", compile_call, ALLOW_EMPTY_GROUP },
-
- { NULL, NULL, false }
+ { "group", compile_group },
+ { "redundant", compile_redundant },
+ { "load-balance", compile_load_balance },
+ { "redundant-load-balance", compile_redundant_load_balance },
+
+ { "case", compile_case },
+ { "foreach", compile_foreach },
+ { "if", compile_if },
+ { "elsif", compile_elsif },
+ { "else", compile_else },
+ { "filter", compile_filter },
+ { "update", compile_update },
+ { "map", compile_map },
+ { "switch", compile_switch },
+ { "parallel", compile_parallel },
+ { "subrequest", compile_subrequest },
+ { "call", compile_call },
+
+ { NULL, NULL, }
};
*modname = "";
}
- /*
- * Some blocks can be empty. The rest need
- * to have contents.
- */
- if (!cf_item_next(cs, NULL) &&
- (compile_table[i].require_children == true)) {
- cf_log_err(ci, "'%s' sections cannot be empty", modrefname);
- return NULL;
- }
-
return compile_table[i].compile(parent, unlang_ctx, cs);
}
}
c = compile_section(parent, &unlang_ctx2, cs, UNLANG_TYPE_GROUP);
if (!c) return NULL;
- c->name = modrefname;
+ c->name = talloc_typed_strdup(c, modrefname);
c->debug_name = talloc_typed_asprintf(c, "%s %s", modrefname, name2);
return c;
}
policy ? UNLANG_TYPE_POLICY : UNLANG_TYPE_GROUP);
if (!c) return NULL;
- c->name = cf_section_name1(subcs);
+ c->name = talloc_typed_strdup(c, cf_section_name1(subcs));
c->debug_name = c->name;
}