📄 parse.c
字号:
/* * Include section calling a module. */ debug_tokens("including module section from file %s\n", buffer); cs = cf_file_read(buffer); if (!cs) { return 0; /* it prints out error messages */ } /* * The outer section is called "main", and can be ignored. * It should be a section, so there should be a subsection. */ subcs = cf_subsection_find_next(cs, NULL, NULL); if (!subcs) { fprintf(stderr, "%s[%d]: Expected section containing modules\n", lexer->filename, lexer->lineno); cf_section_free(&cs); return 0; } section_name = cf_section_name1(subcs); rad_assert(section_name != NULL); component = fr_str2int(policy_component_names, section_name, RLM_COMPONENT_COUNT); if (component == RLM_COMPONENT_COUNT) { fprintf(stderr, "%s[%d]: Invalid section name \"%s\"\n", lexer->filename, lexer->lineno, section_name); cf_section_free(&cs); return 0; } /* * Compile the module entry. */ mc = compile_modgroup(NULL, component, subcs); if (!mc) { cf_section_free(&cs); return 0; /* more often results in calling exit... */ } this = rad_malloc(sizeof(*this)); memset(this, 0, sizeof(*this)); this->item.type = POLICY_TYPE_MODULE; this->item.lineno = lexer->lineno; this->component = component; this->cs = cs; this->mc = mc; *tail = (policy_item_t *) this; return 1;}/* * Parse one statement. 'foo = bar', or 'if (...) {...}', or '{...}', * and so on. */static int parse_statement(policy_lex_file_t *lexer, policy_item_t **tail){ int rcode; policy_reserved_word_t reserved; policy_lex_t token, assign; char lhs[256], rhs[256]; policy_assignment_t *this; /* * See what kind of token we have. */ token = policy_lex_file(lexer, 0, lhs, sizeof(lhs)); switch (token) { case POLICY_LEX_LC_BRACKET: rcode = parse_block(lexer, tail); if (!rcode) { return 0; } break; case POLICY_LEX_BARE_WORD: reserved = fr_str2int(policy_reserved_words, lhs, POLICY_RESERVED_UNKNOWN); switch (reserved) { case POLICY_RESERVED_IF: if (parse_if(lexer, tail)) { return 1; } return 0; break; case POLICY_RESERVED_CONTROL: case POLICY_RESERVED_REQUEST: case POLICY_RESERVED_REPLY: case POLICY_RESERVED_PROXY_REQUEST: case POLICY_RESERVED_PROXY_REPLY: if (parse_attribute_block(lexer, tail, reserved)) return 1; return 0; break; case POLICY_RESERVED_PRINT: if (parse_print(lexer, tail)) { return 1; } return 0; break; case POLICY_RESERVED_RETURN: if (parse_return(lexer, tail)) { return 1; } return 0; break; case POLICY_RESERVED_MODULE: if (parse_module(lexer, tail)) { return 1; } return 0; break; case POLICY_RESERVED_UNKNOWN: /* wasn't a reserved word */ /* * Is a named policy, parse the reference to it. */ if (rlm_policy_find(lexer->policies, lhs) != NULL) { if (!parse_call(lexer, tail, lhs)) { return 0; } return 1; } { const DICT_ATTR *dattr; /* * Bare words MUST be dictionary attributes */ dattr = dict_attrbyname(lhs); if (!dattr) { fprintf(stderr, "%s[%d]: Expected attribute name, got \"%s\"\n", lexer->filename, lexer->lineno, lhs); return 0; } debug_tokens("%s[%d]: Got attribute %s\n", lexer->filename, lexer->lineno, lhs); } break; default: fprintf(stderr, "%s[%d]: Unexpected reserved word \"%s\"\n", lexer->filename, lexer->lineno, lhs); return 0; } /* switch over reserved words */ break; /* * Return from nested blocks. */ case POLICY_LEX_RC_BRACKET: policy_lex_push_token(lexer, token); return 2; /* magic */ case POLICY_LEX_EOF: /* nothing more to do */ return 3; default: fprintf(stderr, "%s[%d]: Unexpected %s\n", lexer->filename, lexer->lineno, fr_int2str(policy_explanations, token, "string")); break; } /* * Parse a bare statement. */ assign = policy_lex_file(lexer, 0, rhs, sizeof(rhs)); switch (assign) { case POLICY_LEX_ASSIGN: case POLICY_LEX_SET_EQUALS: case POLICY_LEX_AND_EQUALS: case POLICY_LEX_OR_EQUALS: case POLICY_LEX_PLUS_EQUALS: break; default: fprintf(stderr, "%s[%d]: Unexpected assign %s\n", lexer->filename, lexer->lineno, fr_int2str(policy_explanations, assign, "string")); return 0; } this = rad_malloc(sizeof(*this)); memset(this, 0, sizeof(*this)); this->item.type = POLICY_TYPE_ASSIGNMENT; this->item.lineno = lexer->lineno; token = policy_lex_file(lexer, 0, rhs, sizeof(rhs)); if ((token != POLICY_LEX_BARE_WORD) && (token != POLICY_LEX_DOUBLE_QUOTED_STRING)) { fprintf(stderr, "%s[%d]: Unexpected rhs %s\n", lexer->filename, lexer->lineno, fr_int2str(policy_explanations, token, "string")); rlm_policy_free_item((policy_item_t *) this); return 0; } this->rhs_type = token; this->rhs = strdup(rhs); token = policy_lex_file(lexer, POLICY_LEX_FLAG_RETURN_EOL, rhs, sizeof(rhs)); if (token != POLICY_LEX_EOL) { fprintf(stderr, "%s[%d]: Expected EOL\n", lexer->filename, lexer->lineno); rlm_policy_free_item((policy_item_t *) this); return 0; } debug_tokens("[ASSIGN %s %s %s]\n", lhs, fr_int2str(rlm_policy_tokens, assign, "?"), rhs); /* * Fill in the assignment struct */ this->lhs = strdup(lhs); this->assign = assign; *tail = (policy_item_t *) this; return 1;}/* * Parse block of statements. The block has already been checked * to begin with a '{'. */static int parse_block(policy_lex_file_t *lexer, policy_item_t **tail){ int rcode; policy_lex_t token; debug_tokens("[BLOCK] "); token = policy_lex_file(lexer, 0, NULL, 0); if (token != POLICY_LEX_LC_BRACKET) { fprintf(stderr, "%s[%d]: Expected '{'\n", lexer->filename, lexer->lineno); return 0; } rcode = 0; while ((rcode = parse_statement(lexer, tail)) != 0) { if (rcode == 2) { token = policy_lex_file(lexer, 0, NULL, 0); if (token != POLICY_LEX_RC_BRACKET) { fprintf(stderr, "%s[%d]: Expected '}'\n", lexer->filename, lexer->lineno); return 0; } return 1; } rad_assert(*tail != NULL); /* parse_statement must fill this in */ while (*tail) tail = &((*tail)->next); } debug_tokens("\n"); /* * Parse statement failed. */ return 0;}/* * Parse debugging statements */static int parse_debug(policy_lex_file_t *lexer){ int rcode = 0; policy_lex_t token; char buffer[32]; token = policy_lex_file(lexer, 0, buffer, sizeof(buffer)); if (token != POLICY_LEX_BARE_WORD) { fprintf(stderr, "%s[%d]: Bad debug command\n", lexer->filename, lexer->lineno); return 0; } if (strcasecmp(buffer, "none") == 0) { lexer->debug = POLICY_DEBUG_NONE; rcode = 1; } else if (strcasecmp(buffer, "peek") == 0) { lexer->debug |= POLICY_DEBUG_PEEK; rcode = 1; } else if (strcasecmp(buffer, "print_tokens") == 0) { lexer->debug |= POLICY_DEBUG_PRINT_TOKENS; rcode = 1; } else if (strcasecmp(buffer, "print_policy") == 0) { lexer->debug |= POLICY_DEBUG_PRINT_POLICY; rcode = 1; } else if (strcasecmp(buffer, "evaluate") == 0) { lexer->debug |= POLICY_DEBUG_EVALUATE; rcode = 1; } if (rcode) { token = policy_lex_file(lexer, POLICY_LEX_FLAG_RETURN_EOL, NULL, 0); if (token != POLICY_LEX_EOL) { fprintf(stderr, "%s[%d]: Expected EOL\n", lexer->filename, lexer->lineno); return 0; } } else { fprintf(stderr, "%s[%d]: Bad debug command \"%s\"\n", lexer->filename, lexer->lineno, buffer); return 0; } return 1;}/* * Parse a named policy "policy foo {...}" */static int parse_named_policy(policy_lex_file_t *lexer){ int rcode; policy_lex_t token; char mystring[256]; policy_named_t *this; DICT_ATTR *dattr; debug_tokens("[POLICY] "); this = rad_malloc(sizeof(*this)); memset(this, 0, sizeof(*this)); this->item.type = POLICY_TYPE_NAMED_POLICY; this->item.lineno = lexer->lineno; token = policy_lex_file(lexer, 0, mystring, sizeof(mystring)); if (token != POLICY_LEX_BARE_WORD) { fprintf(stderr, "%s[%d]: Expected policy name, got \"%s\"\n", lexer->filename, lexer->lineno, fr_int2str(rlm_policy_tokens, token, "?")); rlm_policy_free_item((policy_item_t *) this); return 0; } dattr = dict_attrbyname(mystring); if (dattr) { fprintf(stderr, "%s[%d]: Invalid policy name \"%s\": it is already defined as a dictionary attribute\n", lexer->filename, lexer->lineno, mystring); rlm_policy_free_item((policy_item_t *) this); return 0; } this->name = strdup(mystring); rcode = parse_block(lexer, &(this->policy)); if (!rcode) { rlm_policy_free_item((policy_item_t *) this); return rcode; } /* * And insert it into the tree of policies. * * For now, policy names aren't scoped, they're global. */ if (!rlm_policy_insert(lexer->policies, this)) { radlog(L_ERR, "Failed to insert policy \"%s\"", this->name); rlm_policy_free_item((policy_item_t *) this); return 0; } if ((lexer->debug & POLICY_DEBUG_PRINT_POLICY) != 0) { rlm_policy_print(this); } return 1;}/* * Parse an "include filename" statement * * FIXME: Tie this file into the CONF_SECTION for HUP handling! */static int parse_include(policy_lex_file_t *lexer){ char *p; policy_lex_t token; char filename[1024]; char buffer[2048]; token = policy_lex_file(lexer, 0, filename, sizeof(filename)); if (token != POLICY_LEX_DOUBLE_QUOTED_STRING) { fprintf(stderr, "%s[%d]: Expected filename, got \"%s\"\n", lexer->filename, lexer->lineno, fr_int2str(rlm_policy_tokens, token, "?")); return 0; } /* * See if we're including all of the files in a subdirectory. */ strlcpy(buffer, lexer->filename, sizeof(buffer)); p = strrchr(buffer, '/'); if (p) { strlcpy(p + 1, filename, sizeof(buffer) - 1 - (p - buffer));#ifdef HAVE_DIRENT_H p = strrchr(p + 1, '/'); if (p && !p[1]) { DIR *dir; struct dirent *dp; p++; dir = opendir(buffer); if (!dir) { fprintf(stderr, "%s[%d]: Error opening %s:%s\n", lexer->filename, lexer->lineno, buffer, strerror(errno)); return 0; } /* * Read the directory, ignoring "." files. */ while ((dp = readdir(dir)) != NULL) { struct stat buf; if (dp->d_name[0] == '.') continue; if (strchr(dp->d_name, '~') != NULL) continue; strlcpy(p, dp->d_name, sizeof(buffer) - (p - buffer)); if ((stat(buffer, &buf) != 0) || S_ISDIR(buf.st_mode)) continue; debug_tokens("\nincluding file %s\n", buffer); if (!rlm_policy_parse(lexer->policies, buffer)) { closedir(dir); return 0; } } closedir(dir); return 1; } /* else it must have been a normalx file */#endif } else { snprintf(buffer, sizeof(buffer), "%s/%s", radius_dir, filename); } /* * Handle one include file. */ debug_tokens("\nincluding file %s\n", buffer); if (!rlm_policy_parse(lexer->policies, buffer)) { return 0; } return 1;}/* * Parse data from a file into a policy language. */int rlm_policy_parse(rbtree_t *policies, const char *filename){ FILE *fp; policy_lex_t token; policy_lex_file_t mylexer, *lexer = NULL; char buffer[32]; fp = fopen(filename, "r"); if (!fp) { fprintf(stderr, "Failed to open %s: %s\n", filename, strerror(errno)); return 0; } lexer = &mylexer; memset(lexer, 0, sizeof(*lexer)); lexer->filename = filename; lexer->fp = fp; lexer->token = POLICY_LEX_BAD; lexer->parse = NULL; /* initial input */ lexer->policies = policies; do { int reserved; token = policy_lex_file(lexer, 0, buffer, sizeof(buffer)); switch (token) { case POLICY_LEX_BARE_WORD: reserved = fr_str2int(policy_reserved_words, buffer, POLICY_RESERVED_UNKNOWN); switch (reserved) { case POLICY_RESERVED_POLICY: if (!parse_named_policy(lexer)) { return 0; } break; case POLICY_RESERVED_INCLUDE: if (!parse_include(lexer)) { return 0; } break; case POLICY_RESERVED_DEBUG: if (!parse_debug(lexer)) { return 0; } break; default: fprintf(stderr, "%s[%d]: Unexpected word \"%s\"\n", lexer->filename, lexer->lineno, buffer); return 0; break; } /* switch over reserved words */ case POLICY_LEX_EOF: break; default: fprintf(stderr, "%s[%d]: Illegal input\n", lexer->filename, lexer->lineno); return 0; } } while (token != POLICY_LEX_EOF); if (((lexer->debug & POLICY_DEBUG_PRINT_POLICY) != 0) && fr_log_fp) { fprintf(fr_log_fp, "# rlm_policy \n"); } debug_tokens("--------------------------------------------------\n"); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -