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

📄 modcall.c

📁 radius server在linux下的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * modcall.c * * Version:	$Id: modcall.c,v 1.22.2.1 2005/02/09 18:19:00 aland Exp $ * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Copyright 2000  The FreeRADIUS server project */#include <stdlib.h>#include <string.h>#include <stdarg.h>#include "radiusd.h"#include "rad_assert.h"#include "conffile.h"#include "modpriv.h"#include "modules.h"#include "modcall.h"/* mutually-recursive static functions need a prototype up front */static modcallable *do_compile_modgroup(int, CONF_SECTION *, const char *,		int, int);/* Actions may be a positive integer (the highest one returned in the group * will be returned), or the keyword "return", represented here by * MOD_ACTION_RETURN, to cause an immediate return. * There's also the keyword "reject", represented here by MOD_ACTION_REJECT * to cause an immediate reject. */#define MOD_ACTION_RETURN (-1)#define MOD_ACTION_REJECT (-2)/* Here are our basic types: modcallable, modgroup, and modsingle. For an * explanation of what they are all about, see ../../doc/README.failover */struct modcallable {	struct modcallable *next;	int actions[RLM_MODULE_NUMCODES];	const char *name;	enum { MOD_SINGLE, MOD_GROUP } type;};typedef struct {	modcallable mc;	modcallable *children;} modgroup;typedef struct {	modcallable mc;	module_instance_t *modinst;} modsingle;/* Simple conversions: modsingle and modgroup are subclasses of modcallable, * so we often want to go back and forth between them. */static modsingle *mod_callabletosingle(modcallable *p){	rad_assert(p->type==MOD_SINGLE);	return (modsingle *)p;}static modgroup *mod_callabletogroup(modcallable *p){	rad_assert(p->type==MOD_GROUP);	return (modgroup *)p;}static modcallable *mod_singletocallable(modsingle *p){	return (modcallable *)p;}static modcallable *mod_grouptocallable(modgroup *p){	return (modcallable *)p;}/* modgroups are grown by adding a modcallable to the end */static void add_child(modgroup *g, modcallable *c){	modcallable **head = &g->children;	modcallable *node = *head;	modcallable **last = head;	while (node) {		last = &node->next;		node = node->next;	}	rad_assert(c->next == NULL);	*last = c;}/* Here's where we recognize all of our keywords: first the rcodes, then the * actions */static LRAD_NAME_NUMBER rcode_table[] = {	{ "reject",     RLM_MODULE_REJECT       },	{ "fail",       RLM_MODULE_FAIL         },	{ "ok",         RLM_MODULE_OK           },	{ "handled",    RLM_MODULE_HANDLED      },	{ "invalid",    RLM_MODULE_INVALID      },	{ "userlock",   RLM_MODULE_USERLOCK     },	{ "notfound",   RLM_MODULE_NOTFOUND     },	{ "noop",       RLM_MODULE_NOOP         },	{ "updated",    RLM_MODULE_UPDATED      },	{ NULL, 0 }};static int str2rcode(const char *s, const char *filename, int lineno){	int rcode;	rcode = lrad_str2int(rcode_table, s, -1);	if (rcode < 0) {		radlog(L_ERR|L_CONS,		       "%s[%d] Unknown module rcode '%s'.\n",		       filename, lineno, s);		exit(1);	}	return rcode;}static int str2action(const char *s, const char *filename, int lineno){	if(!strcasecmp(s, "return"))		return MOD_ACTION_RETURN;	else if(!strcasecmp(s, "reject"))		return MOD_ACTION_REJECT;	else if (strspn(s, "0123456789")==strlen(s)) {		int rcode = atoi(s);		/*		 *	Don't allow priority zero, for future use.		 */		if (rcode == 0) {			radlog(L_ERR|L_CONS,			       "%s[%d] Invalid action '%s'.\n",			       filename, lineno, s);			exit(1);		}		return rcode;	} else {		radlog(L_ERR|L_CONS,				"%s[%d] Unknown action '%s'.\n",				filename, lineno, s);		exit(1);	}	return -1;}#if 0static const char *action2str(int action){	static char buf[32];	if(action==MOD_ACTION_RETURN)		return "return";	if(action==MOD_ACTION_REJECT)		return "reject";	snprintf(buf, sizeof buf, "%d", action);	return buf;}#endif/* Some short names for debugging output */static const char *comp2str[] = {	"authenticate",	"authorize",	"preacct",	"accounting",	"session",	"pre-proxy",	"post-proxy",	"post-auth"};#ifdef HAVE_PTHREAD_H/* *	Lock the mutex for the module */static void safe_lock(module_instance_t *instance){	if (instance->mutex)		pthread_mutex_lock(instance->mutex);}/* *	Unlock the mutex for the module */static void safe_unlock(module_instance_t *instance){	if (instance->mutex)		pthread_mutex_unlock(instance->mutex);}#else/* *	No threads: these functions become NULL's. */#define safe_lock(foo)#define safe_unlock(foo)#endifstatic int call_modsingle(int component, modsingle *sp, REQUEST *request,			  int default_result){	int myresult = default_result;	DEBUG3("  modsingle[%s]: calling %s (%s) for request %d",	       comp2str[component], sp->modinst->name,	       sp->modinst->entry->name, request->number);	safe_lock(sp->modinst);	myresult = sp->modinst->entry->module->methods[component](			sp->modinst->insthandle, request);	safe_unlock(sp->modinst);	DEBUG3("  modsingle[%s]: returned from %s (%s) for request %d",	       comp2str[component], sp->modinst->name,	       sp->modinst->entry->name, request->number);	return myresult;}static int call_modgroup(int component, modgroup *g, REQUEST *request,		int default_result){	int myresult = default_result;	int myresultpref;	modcallable *p;	/*	 *	Catch people who have issues.	 */	if (!g->children) {		DEBUG2("  WARNING! Asked to process empty group.  Returning %s.", lrad_int2str(rcode_table, myresult, "??"));		return default_result;	}	/* Assign the lowest possible preference to the default return code */	myresultpref = 0;	/* Loop over the children */	for(p = g->children; p; p = p->next) {		int r = RLM_MODULE_FAIL;		/* Call this child by recursing into modcall */		r = modcall(component, p, request);#if 0		DEBUG2("%s: action for %s is %s",			comp2str[component], lrad_int2str(rcode_table, r, "??"),			action2str(p->actions[r]));#endif		/* Find an action to go with the child's result. If "return",		 * break out of the loop so the rest of the children in the		 * list will be skipped. */		if(p->actions[r] == MOD_ACTION_RETURN) {			myresult = r;			break;		}		/* If "reject" break out of the loop and return reject */		if (p->actions[r] == MOD_ACTION_REJECT) {			myresult = RLM_MODULE_REJECT;			break;		}		/* Otherwise, the action is a number, the preference level of		 * this return code. If no higher preference has been seen		 * yet, remember this one. */		if(p->actions[r] >= myresultpref) {			myresult = r;			myresultpref = p->actions[r];		}	}	return myresult;}int modcall(int component, modcallable *c, REQUEST *request){	int myresult;	/* Choose a default return value appropriate for the component */	switch(component) {	case RLM_COMPONENT_AUTZ:		myresult = RLM_MODULE_NOTFOUND;		break;	case RLM_COMPONENT_AUTH:		myresult = RLM_MODULE_REJECT;		break;	case RLM_COMPONENT_PREACCT:		myresult = RLM_MODULE_NOOP;		break;	case RLM_COMPONENT_ACCT:		myresult = RLM_MODULE_NOOP;		break;	case RLM_COMPONENT_SESS:		myresult = RLM_MODULE_FAIL;		break;	case RLM_COMPONENT_PRE_PROXY:		myresult = RLM_MODULE_NOOP;		break;	case RLM_COMPONENT_POST_PROXY:		myresult = RLM_MODULE_NOOP;		break;	case RLM_COMPONENT_POST_AUTH:		myresult = RLM_MODULE_NOOP;		break;	default:		myresult = RLM_MODULE_FAIL;		break;	}	if(c == NULL) {		DEBUG2("modcall[%s]: NULL object returns %s for request %d",		       comp2str[component],		       lrad_int2str(rcode_table, myresult, "??"),		       request->number);		return myresult;	}	if(c->type==MOD_GROUP) {		modgroup *g = mod_callabletogroup(c);		DEBUG2("modcall: entering group %s for request %d",		       c->name, request->number);		myresult = call_modgroup(component, g, request, myresult);		DEBUG2("modcall: group %s returns %s for request %d",		        c->name,		       lrad_int2str(rcode_table, myresult, "??"),		       request->number);	} else {		modsingle *sp = mod_callabletosingle(c);		myresult = call_modsingle(component, sp, request, myresult);		DEBUG2("  modcall[%s]: module \"%s\" returns %s for request %d",		       comp2str[component], c->name,		       lrad_int2str(rcode_table, myresult, "??"),		       request->number);	}	return myresult;}#if 0/* If you suspect a bug in the parser, you'll want to use these dump * functions. dump_tree should reproduce a whole tree exactly as it was found * in radiusd.conf, but in long form (all actions explicitly defined) */static void dump_mc(modcallable *c, int indent){	int i;	if(c->type==MOD_SINGLE) {		modsingle *single = mod_callabletosingle(c);		DEBUG("%.*s%s {", indent, "\t\t\t\t\t\t\t\t\t\t\t",			single->modinst->name);	} else {		modgroup *g = mod_callabletogroup(c);		modcallable *p;		DEBUG("%.*sgroup {", indent, "\t\t\t\t\t\t\t\t\t\t\t");		for(p = g->children;p;p = p->next)			dump_mc(p, indent+1);	}	for(i = 0; i<RLM_MODULE_NUMCODES; ++i) {		DEBUG("%.*s%s = %s", indent+1, "\t\t\t\t\t\t\t\t\t\t\t",		      lrad_int2str(rcode_table, i, "??"),		      action2str(c->actions[i]));	}	DEBUG("%.*s}", indent, "\t\t\t\t\t\t\t\t\t\t\t");}static void dump_tree(int comp, modcallable *c){	DEBUG("[%s]", comp2str[comp]);	dump_mc(c, 0);}#elsestatic void dump_tree(int comp UNUSED, modcallable *c UNUSED){	return;}#endif#define GROUPTYPE_SIMPLEGROUP 0#define GROUPTYPE_REDUNDANT 1#define GROUPTYPE_APPEND 2#define GROUPTYPE_COUNT 3/* These are the default actions. For each component, the group{} block * behaves like the code from the old module_*() function. redundant{} and * append{} are based on my guesses of what they will be used for. --Pac. */static intdefaultactions[RLM_COMPONENT_COUNT][GROUPTYPE_COUNT][RLM_MODULE_NUMCODES] ={	/* authenticate */	{		/* group */		{			MOD_ACTION_RETURN,	/* reject   */			1,			/* fail     */			MOD_ACTION_RETURN,	/* ok       */			MOD_ACTION_RETURN,	/* handled  */			1,			/* invalid  */			MOD_ACTION_RETURN,	/* userlock */			MOD_ACTION_RETURN,	/* notfound */			1,			/* noop     */			1			/* updated  */		},		/* redundant */		{			MOD_ACTION_RETURN,	/* reject   */			1,			/* fail     */			MOD_ACTION_RETURN,	/* ok       */			MOD_ACTION_RETURN,	/* handled  */			MOD_ACTION_RETURN,	/* invalid  */			MOD_ACTION_RETURN,	/* userlock */			MOD_ACTION_RETURN,	/* notfound */			MOD_ACTION_RETURN,	/* noop     */			MOD_ACTION_RETURN	/* updated  */		},		/* append */		{			MOD_ACTION_RETURN,	/* reject   */			1,			/* fail     */			MOD_ACTION_RETURN,	/* ok       */			MOD_ACTION_RETURN,	/* handled  */			MOD_ACTION_RETURN,	/* invalid  */			MOD_ACTION_RETURN,	/* userlock */			2,			/* notfound */			MOD_ACTION_RETURN,	/* noop     */			MOD_ACTION_RETURN	/* updated  */		}	},	/* authorize */	{		/* group */		{			MOD_ACTION_RETURN,	/* reject   */			MOD_ACTION_RETURN,	/* fail     */			3,			/* ok       */			MOD_ACTION_RETURN,	/* handled  */			MOD_ACTION_RETURN,	/* invalid  */			MOD_ACTION_RETURN,	/* userlock */			1,			/* notfound */			2,			/* noop     */			4			/* updated  */		},		/* redundant */		{			MOD_ACTION_RETURN,	/* reject   */			1,			/* fail     */			MOD_ACTION_RETURN,	/* ok       */			MOD_ACTION_RETURN,	/* handled  */			MOD_ACTION_RETURN,	/* invalid  */			MOD_ACTION_RETURN,	/* userlock */			MOD_ACTION_RETURN,	/* notfound */			MOD_ACTION_RETURN,	/* noop     */			MOD_ACTION_RETURN	/* updated  */		},		/* append */		{

⌨️ 快捷键说明

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