⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 evaluate.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
			 *	instead take an operator, a pointer to			 *	the comparison result, and return			 *	"true/false" for "comparions			 *	succeeded/failed", which are different			 *	error codes than "comparison is less			 *	than, equal to, or greater than zero".			 */			compare = radius_callback_compare(state->request,							  vp, myvp, NULL, NULL);			pairfree(&myvp);		} else {			/*			 *	FIXME: Do something for RHS type?			 */			fr_printf_log("CMP %s %s\n", lhs_buffer, this->rhs);			compare = strcmp(lhs_buffer, this->rhs);		}		debug_evaluate("CONDITION COMPARE %d\n", compare);		switch (this->compare) {		case POLICY_LEX_CMP_EQUALS:			rcode = (compare == 0);			break;		case POLICY_LEX_CMP_NOT_EQUALS:			rcode = (compare != 0);			break;		case POLICY_LEX_LT:			rcode = (compare < 0);			break;		case POLICY_LEX_GT:			rcode = (compare > 0);			break;		case POLICY_LEX_LE:			rcode =(compare <= 0);			break;		case POLICY_LEX_GE:			rcode = (compare >= 0);			break;#ifdef HAVE_REGEX_H		case POLICY_LEX_RX_EQUALS:		{ /* FIXME: copied from src/main/valuepair.c */			int i;			regmatch_t rxmatch[REQUEST_MAX_REGEX + 1];			/*			 *	Include substring matches.			 */			if (regcomp(&reg, this->rhs,				    REG_EXTENDED) != 0) {				/* FIXME: print error */				return FALSE;			}			rad_assert(data != NULL);			rcode = regexec(&reg, data,					REQUEST_MAX_REGEX + 1,					rxmatch, 0);			rcode = (rcode == 0);			regfree(&reg);			/*			 *	Add %{0}, %{1}, etc.			 */			for (i = 0; i <= REQUEST_MAX_REGEX; i++) {				char *p;				char rxbuffer[256];				/*				 *	Didn't match: delete old				 *	match, if it existed.				 */				if (!rcode ||				    (rxmatch[i].rm_so == -1)) {					p = request_data_get(state->request, state->request,							     REQUEST_DATA_REGEX | i);					if (p) {						free(p);						continue;					}					/*					 *	No previous match					 *	to delete, stop.					 */					break;				}				/*				 *	Copy substring into buffer.				 */				memcpy(rxbuffer,				       data + rxmatch[i].rm_so,				       rxmatch[i].rm_eo - rxmatch[i].rm_so);				rxbuffer[rxmatch[i].rm_eo - rxmatch[i].rm_so] = '\0';				/*				 *	Copy substring, and add it to				 *	the request.				 *				 *	Note that we don't check				 *	for out of memory, which is				 *	the only error we can get...				 */				p = strdup(rxbuffer);				request_data_add(state->request,						 state->request,						 REQUEST_DATA_REGEX | i,						 p, free);			}		}		break;		case POLICY_LEX_RX_NOT_EQUALS:			regcomp(&reg, this->rhs, REG_EXTENDED|REG_NOSUB);			rad_assert(data != NULL);			rcode = regexec(&reg, data,					0, NULL, 0);			rcode = (rcode != 0);			regfree(&reg);				break;#endif /* HAVE_REGEX_H */		default:			rcode = FALSE;			break;		} /* switch over comparison operators */		break;		/* default from first switch over compare */	}	if (this->sense) rcode = (rcode == FALSE); /* reverse sense of test */	/*	 *	No trailing &&, ||	 */	switch (this->child_condition) {	default:		return rcode;	case POLICY_LEX_L_AND:		if (!rcode) return rcode; /* FALSE && x == FALSE */		break;	case POLICY_LEX_L_OR:		if (rcode) return rcode; /* TRUE && x == TRUE */		break;	}	/*	 *	Tail recursion.	 */	this = (const policy_condition_t *) this->child;	goto redo;	return 1;		/* should never reach here */}/* *	Evaluate an 'if' statement */static int evaluate_if(policy_state_t *state, const policy_item_t *item){	int rcode;	const policy_if_t *this;	this = (const policy_if_t *) item;	/*	 *	evaluate_condition calls itself recursively.	 *	We should probably allocate a new state, instead.	 */	rcode = evaluate_condition(state, this->condition);	debug_evaluate("IF condition returned %s\n",	       rcode ? "true" : "false");	if (rcode) {		rcode = policy_stack_push(state, this->if_true);		if (!rcode) return rcode;	} else if (this->if_false) {		rcode = policy_stack_push(state, this->if_false);		if (!rcode) return rcode;	}	/*	 *	'if' can fail, if the block it's processing fails.	 */	return 1;;}/* *	Make a VALUE_PAIR from a policy_assignment_t* * *	The assignment operator has to be '='. */static VALUE_PAIR *assign2vp(REQUEST *request,			     const policy_assignment_t *assign){	VALUE_PAIR *vp;	FR_TOKEN operator = T_OP_EQ;	const char *value = assign->rhs;	char buffer[2048];	if ((assign->rhs_type == POLICY_LEX_DOUBLE_QUOTED_STRING) &&	    (strchr(assign->rhs, '%') != NULL)) {		radius_xlat(buffer, sizeof(buffer), assign->rhs,			    request, NULL);		value = buffer;	}	/*	 *	This is crappy.. fix it.	 */	switch (assign->assign) {	case POLICY_LEX_ASSIGN:		operator = T_OP_EQ;		break;	case POLICY_LEX_SET_EQUALS:		operator = T_OP_SET;		break;	case POLICY_LEX_PLUS_EQUALS:		operator = T_OP_ADD;		break;	default:		fprintf(stderr, "Expected '=' for operator, not '%s' at line %d\n",			fr_int2str(rlm_policy_tokens,				     assign->assign, "?"),			assign->item.lineno);		return NULL;	}	vp = pairmake(assign->lhs, value, operator);	if (!vp) {		fprintf(stderr, "Failed creating pair: %s %s\n", value, librad_errstr);	}	return vp;}/* *	Evaluate a 'packet .= {attrs}' statement */static int evaluate_attr_list(policy_state_t *state, const policy_item_t *item){	const policy_attributes_t *this;	VALUE_PAIR **vps = NULL;	VALUE_PAIR *vp, *head, **tail;	const policy_item_t *attr;	policy_lex_t this_how;	this = (const policy_attributes_t *) item;	switch (this->where) {	case POLICY_RESERVED_CONTROL:		vps = &(state->request->config_items);		break;	case POLICY_RESERVED_REQUEST:		vps = &(state->request->packet->vps);		break;	case POLICY_RESERVED_REPLY:		vps = &(state->request->reply->vps);		break;	case POLICY_RESERVED_PROXY_REQUEST:		if (!state->request->proxy) return 0; /* FIXME: print error */		vps = &(state->request->proxy->vps);		break;	case POLICY_RESERVED_PROXY_REPLY:		if (!state->request->proxy_reply) return 0; /* FIXME: print error */		vps = &(state->request->proxy_reply->vps);		break;	default:		return 0;	}	head = NULL;	tail = &head;	for (attr = this->attributes; attr != NULL; attr = attr->next) {		if (attr->type != POLICY_TYPE_ASSIGNMENT) {			fprintf(stderr, "bad assignment in attribute list at line %d\n", attr->lineno);			pairfree(&head);			return 0;		}		vp = assign2vp(state->request, (const policy_assignment_t *) attr);		if (!vp) {			fprintf(stderr, "Failed to allocate VP\n");			pairfree(&head);			return 0;		}		*tail = vp;		tail = &(vp->next);	}	this_how = this->how; retry_how:	switch (this_how) {	case POLICY_LEX_SET_EQUALS: /* dangerous: removes all previous things! */		pairfree(vps);		*vps = head;		break;	case POLICY_LEX_AFTER_TAIL_ASSIGN:		pairmove(vps, &head);		pairfree(&head);		break;	case POLICY_LEX_ASSIGN: /* 'union' */		pairmove(vps, &head);		pairfree(&head);		break;	case POLICY_LEX_BEFORE_HEAD_ASSIGN:		pairmove(&head, vps);		pairfree(vps);		*vps = head;		break;	case POLICY_LEX_AFTER_TAIL_EQUALS:	case POLICY_LEX_CONCAT_EQUALS:		pairadd(vps, head);		break;	case POLICY_LEX_BEFORE_HEAD_EQUALS:		pairadd(&head, *vps);		*vps = head;		break;	case POLICY_LEX_BEFORE_WHERE_EQUALS:	case POLICY_LEX_AFTER_WHERE_EQUALS:	case POLICY_LEX_BEFORE_WHERE_ASSIGN:	case POLICY_LEX_AFTER_WHERE_ASSIGN:		/* find location*/		{			VALUE_PAIR *vpprev = NULL, *vpnext = NULL, *lvp;			for(lvp = *vps; lvp; vpprev = lvp, lvp = lvp->next) {				vpnext = lvp->next;				lvp->next = NULL;				if (evaluate_condition(state, this->where_loc))					break;				lvp->next = vpnext;			}			if (lvp) { 				switch(this_how) {				case POLICY_LEX_BEFORE_WHERE_EQUALS:				case POLICY_LEX_BEFORE_WHERE_ASSIGN:					if (vpprev) {						lvp->next = vpnext;						vpnext = lvp;						vpprev->next = NULL;						lvp = vpprev;					}				default: /* always reached */					break;				}				switch(this_how) {				case POLICY_LEX_BEFORE_WHERE_EQUALS:					if (vpprev) 						pairadd(&lvp, head);					else						*vps = lvp = head;					break; 				case POLICY_LEX_AFTER_WHERE_EQUALS: 					pairadd(&lvp, head);					break;				case POLICY_LEX_BEFORE_WHERE_ASSIGN:					if (vpprev) {						pairmove(&lvp, &head);						pairfree(&head);					}					else						*vps = lvp = head;					break;				case POLICY_LEX_AFTER_WHERE_ASSIGN:					pairmove(&lvp, &head);					pairfree(&head);					break;				default:/*never reached*/					break;				}					for( ; lvp && lvp->next; lvp = lvp->next);				if (lvp)					lvp->next = vpnext;				break;			}			switch(this_how) {				case POLICY_LEX_BEFORE_WHERE_EQUALS:					this_how = POLICY_LEX_BEFORE_HEAD_EQUALS;					break;				case POLICY_LEX_AFTER_WHERE_EQUALS:					this_how = POLICY_LEX_AFTER_TAIL_EQUALS;					break;				case POLICY_LEX_BEFORE_WHERE_ASSIGN:					this_how = POLICY_LEX_BEFORE_HEAD_ASSIGN;					break;				case POLICY_LEX_AFTER_WHERE_ASSIGN:					this_how = POLICY_LEX_AFTER_TAIL_ASSIGN;					break;				default: /*never reached*/					break;			}			goto retry_how; 		}		/* FALL-THROUGH */	default:		fprintf(stderr, "HUH?\n");		pairfree(&head);		return 0;	}	state->rcode = RLM_MODULE_UPDATED; /* we did stuff */	return 1;}/* *	Evaluate a reference call to a module. */static int evaluate_call(policy_state_t *state, const policy_item_t *item){	int rcode;	const policy_call_t *this;	const policy_named_t *policy;	this = (const policy_call_t *) item;	policy = rlm_policy_find(state->inst->policies, this->name);	if (!policy) return 0;	/* not found... */	DEBUG2("rlm_policy: Evaluating policy %s", this->name);	rad_assert(policy->policy->type != POLICY_TYPE_BAD);	rad_assert(policy->policy->type < POLICY_TYPE_NUM_TYPES);	/*	 *	Push the name of the function onto the stack,	 *	so that we can catch recursive calls.	 *	 *	The "pop" function will skip over it when it sees it.	 */	rcode = policy_stack_push(state, (const policy_item_t *) policy);	if (!rcode) {		return rcode;	}	/*	 *	Push it onto the stack.  Other code will take care of	 *	calling it.	 */	rcode = policy_stack_push(state, policy->policy);	if (!rcode) {		return rcode;	}	return 1;}/* *	Evaluate a return statement */static int evaluate_return(policy_state_t *state, const policy_item_t *item){	const policy_return_t *this;	this = (const policy_return_t *) item;	state->rcode = this->rcode;	return 1;		/* we succeeded */}/* *	Evaluate a module statement */static int evaluate_module(policy_state_t *state, const policy_item_t *item){	const policy_module_t *this;	this = (const policy_module_t *) item;	/*	 *	Just to be paranoid.  Maybe we want to loosen this	 *	restriction in the future?	 */	if (this->component != state->component) {		DEBUG2("rlm_policy: Cannot mix & match components");		return 0;	}	DEBUG2("rlm_policy: begin nested call");	state->rcode = modcall(this->component, this->mc, state->request);	DEBUG2("rlm_policy: end nested call");	return 1;		/* we succeeded */}/* *	State machine stuff. */typedef int (*policy_evaluate_type_t)(policy_state_t *, const policy_item_t *);/* *	MUST be kept in sync with policy_type_t */static policy_evaluate_type_t evaluate_functions[POLICY_TYPE_NUM_TYPES] = {	NULL,			/* POLICY_TYPE_BAD */	evaluate_if,	evaluate_condition,	evaluate_assignment,	evaluate_attr_list,	evaluate_print,	NULL,			/* define a named policy.. */	evaluate_call,	evaluate_return,	evaluate_module};/* *	Evaluate a policy, keyed by name. */static int policy_evaluate_name(policy_state_t *state, const char *name){	int rcode;	const policy_item_t *this;	policy_named_t mypolicy, *policy;	mypolicy.name = name;	policy = rbtree_finddata(state->inst->policies, &mypolicy);	if (!policy) return RLM_MODULE_FAIL;	DEBUG2("rlm_policy: Evaluating policy %s", name);	rad_assert(policy->item.type != POLICY_TYPE_BAD);	rad_assert(policy->item.type < POLICY_TYPE_NUM_TYPES);	rcode = policy_stack_push(state, policy->policy);	if (!rcode) {		return RLM_MODULE_FAIL;	}	/*	 *	FIXME: Look for magic keywords like "return",	 *	where the packet gets accepted/rejected/whatever	 */	while (policy_stack_pop(state, &this)) {		rad_assert(this != NULL);		rad_assert(this->type != POLICY_TYPE_BAD);		rad_assert(this->type < POLICY_TYPE_NUM_TYPES);		debug_evaluate("Evaluating at line %d\n",			       this->lineno);		rcode = (*evaluate_functions[this->type])(state,							  this);		if (!rcode) {			return RLM_MODULE_FAIL;		}	} /* loop until the stack is empty */	return state->rcode;}/* *	Evaluate, which is pretty close to print, but we look at what *	we're printing. */int rlm_policy_evaluate(rlm_policy_t *inst, REQUEST *request, const char *name){	int rcode;	policy_state_t *state;	state = rad_malloc(sizeof(*state));	memset(state, 0, sizeof(*state));	state->request = request;	state->inst = inst;	state->rcode = RLM_MODULE_OK;	state->component = fr_str2int(policy_component_names, name,					RLM_COMPONENT_COUNT);	rcode = policy_evaluate_name(state, name);	free(state);	return rcode;		/* evaluated OK. */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -