#define MAX_ARGV (16)
+typedef enum {
+ NEST_NONE = 0,
+ NEST_ROOT,
+ NEST_PROTOCOL,
+ NEST_VENDOR,
+ NEST_TLV,
+} dict_nest_t;
+
/** Parser context for dict_from_file
*
* Allows vendor and TLV context to persist across $INCLUDEs
char *filename; //!< name of the file we're reading
int line; //!< line number of this file
fr_dict_attr_t const *da; //!< the da we care about
- fr_type_t nest; //!< for manual vs automatic begin / end things
+ dict_nest_t nest; //!< for manual vs automatic begin / end things
int member_num; //!< structure member numbers
ssize_t struct_size; //!< size of the struct.
} dict_tokenize_frame_t;
return 0;
}
+static dict_tokenize_frame_t const *dict_gctx_find_frame(dict_tokenize_ctx_t *ctx, dict_nest_t nest)
+{
+ int i;
+
+ for (i = ctx->stack_depth; i > 0; i--) {
+ if (ctx->stack[i].nest == nest) return &ctx->stack[i];
+ }
+
+ return NULL;
+}
+
static int dict_gctx_push(dict_tokenize_ctx_t *ctx, fr_dict_attr_t const *da)
{
static fr_dict_attr_t const *dict_gctx_unwind(dict_tokenize_ctx_t *ctx)
{
while ((ctx->stack_depth > 0) &&
- (ctx->stack[ctx->stack_depth].nest == FR_TYPE_NULL)) {
+ (ctx->stack[ctx->stack_depth].nest == NEST_NONE)) {
ctx->stack_depth--;
}
memset(&base_flags, 0, sizeof(base_flags));
while (fgets(buf, sizeof(buf), fp) != NULL) {
+ dict_tokenize_frame_t const *frame;
+
ctx->stack[ctx->stack_depth].line = ++line;
switch (buf[0]) {
}
while (ctx->stack_depth > stack_depth) {
- if (ctx->stack[ctx->stack_depth].nest == FR_TYPE_NULL) {
+ if (ctx->stack[ctx->stack_depth].nest == NEST_NONE) {
ctx->stack_depth--;
continue;
}
goto error;
}
+ frame = dict_gctx_find_frame(ctx, NEST_PROTOCOL);
+ if (frame) {
+ fr_strerror_printf_push("Nested BEGIN-PROTOCOL is forbidden. Previous definition is at %s[%d]",
+ frame->filename, frame->line);
+ goto error;
+ }
+
/*
* Add a temporary fixup pool
*
ctx->dict = found;
if (dict_gctx_push(ctx, ctx->dict->root) < 0) goto error;
- ctx->stack[ctx->stack_depth].nest = FR_TYPE_MAX;
+ ctx->stack[ctx->stack_depth].nest = NEST_PROTOCOL;
continue;
}
/*
* Pop the stack until we get to a PROTOCOL nesting.
*/
- while ((ctx->stack_depth > 0) && (ctx->stack[ctx->stack_depth].nest != FR_TYPE_MAX)) {
+ while ((ctx->stack_depth > 0) && (ctx->stack[ctx->stack_depth].nest != NEST_PROTOCOL)) {
if (ctx->stack[ctx->stack_depth].nest != FR_TYPE_NULL) {
fr_strerror_printf_push("END-PROTOCOL %s with mismatched BEGIN-??? %s", argv[1],
ctx->stack[ctx->stack_depth].da->name);
}
if (dict_gctx_push(ctx, da) < 0) goto error;
- ctx->stack[ctx->stack_depth].nest = FR_TYPE_TLV;
+ ctx->stack[ctx->stack_depth].nest = NEST_TLV;
continue;
} /* BEGIN-TLV */
/*
* Pop the stack until we get to a TLV nesting.
*/
- while ((ctx->stack_depth > 0) && (ctx->stack[ctx->stack_depth].nest != FR_TYPE_TLV)) {
+ while ((ctx->stack_depth > 0) && (ctx->stack[ctx->stack_depth].nest != NEST_TLV)) {
if (ctx->stack[ctx->stack_depth].nest != FR_TYPE_NULL) {
fr_strerror_printf_push("END-TLV %s with mismatched BEGIN-??? %s", argv[1],
ctx->stack[ctx->stack_depth].da->name);
fr_strerror_printf_push("BEGIN-VENDOR is forbidden for protocol %s - it has no ATTRIBUTE of type 'vsa'",
ctx->dict->root->name);
goto error;
+ }
+ frame = dict_gctx_find_frame(ctx, NEST_VENDOR);
+ if (frame) {
+ fr_strerror_printf_push("Nested BEGIN-VENDOR is forbidden. Previous definition is at %s[%d]",
+ frame->filename, frame->line);
+ goto error;
}
/*
}
if (dict_gctx_push(ctx, vendor_da) < 0) goto error;
- ctx->stack[ctx->stack_depth].nest = FR_TYPE_VENDOR;
+ ctx->stack[ctx->stack_depth].nest = NEST_VENDOR;
continue;
} /* BEGIN-VENDOR */
/*
* Pop the stack until we get to a VENDOR nesting.
*/
- while ((ctx->stack_depth > 0) && (ctx->stack[ctx->stack_depth].nest != FR_TYPE_VENDOR)) {
+ while ((ctx->stack_depth > 0) && (ctx->stack[ctx->stack_depth].nest != NEST_VENDOR)) {
if (ctx->stack[ctx->stack_depth].nest != FR_TYPE_NULL) {
fr_strerror_printf_push("END-VENDOR %s with mismatched BEGIN-??? %s", argv[1],
ctx->stack[ctx->stack_depth].da->name);
dict_fixup_init(NULL, &ctx.fixup);
ctx.stack[0].dict = dict;
ctx.stack[0].da = dict->root;
- ctx.stack[0].nest = FR_TYPE_MAX;
+ ctx.stack[0].nest = NEST_ROOT;
ret = _dict_from_file(&ctx, dir_name, filename, src_file, src_line);
if (ret < 0) {
ctx.dict = dict;
ctx.stack[0].dict = dict;
ctx.stack[0].da = dict->root;
- ctx.stack[0].nest = FR_TYPE_MAX;
+ ctx.stack[0].nest = NEST_ROOT;
if (dict_fixup_init(NULL, &ctx.fixup) < 0) return -1;