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

📄 rlm_perl.c

📁 新的radius程序
💻 C
📖 第 1 页 / 共 3 页
字号:
			break;		}	}	if (found == NULL) {		if (inst->perl_pool->current_clones < inst->perl_pool->max_clones ) {			found = pool_grow(inst);			if (found == NULL) {				radlog(L_ERR,"Cannot grow pool returning");				MUTEX_UNLOCK(&inst->perl_pool->mutex);				return NULL;			}		} else {			radlog(L_ERR,"rlm_perl:: reached maximum clones %d cannot grow",					inst->perl_pool->current_clones);			MUTEX_UNLOCK(&inst->perl_pool->mutex);			return NULL;		}	}	move2tail(found, inst);	found->status = busy;	MUTEX_LOCK(&found->lock);	inst->perl_pool->active_clones++;	found->request_count++;	/*	 * Hurry Up	 */	MUTEX_UNLOCK(&inst->perl_pool->mutex);	radlog(L_DBG,"perl_pool: item 0x%lx asigned new request. Handled so far: %d",			(unsigned long) found->clone, found->request_count);	return found;}static int pool_release(POOL_HANDLE *handle, PERL_INST *inst) {	POOL_HANDLE *tmp, *tmp2;	int spare, i, t;	time_t	now;	/*	 * Lock it	 */	MUTEX_LOCK(&inst->perl_pool->mutex);	/*	 * If detach is set then just release the mutex	 */	if (inst->perl_pool->detach == yes ) {	handle->status = idle;		MUTEX_UNLOCK(&handle->lock);		MUTEX_UNLOCK(&inst->perl_pool->mutex);		return 0;	}	MUTEX_UNLOCK(&handle->lock);	handle->status = idle;	inst->perl_pool->active_clones--;	spare = inst->perl_pool->current_clones - inst->perl_pool->active_clones;	radlog(L_DBG,"perl_pool total/active/spare [%d/%d/%d]"			, inst->perl_pool->current_clones, inst->perl_pool->active_clones, spare);	if (spare < inst->perl_pool->min_spare_clones) {		t = inst->perl_pool->min_spare_clones - spare;		for (i=0;i<t; i++) {			if ((tmp = pool_grow(inst)) == NULL) {				MUTEX_UNLOCK(&inst->perl_pool->mutex);				return -1;			}		}		MUTEX_UNLOCK(&inst->perl_pool->mutex);		return 0;	}	now = time(NULL);	if ((now - inst->perl_pool->time_when_last_added) < inst->perl_pool->cleanup_delay) {		MUTEX_UNLOCK(&inst->perl_pool->mutex);		return 0;	}	if (spare > inst->perl_pool->max_spare_clones) {		spare -= inst->perl_pool->max_spare_clones;		for (tmp = inst->perl_pool->head; (tmp !=NULL ) && (spare > 0) ; tmp = tmp2) {			tmp2 = tmp->next;			if(tmp->status == idle) {				rlm_destroy_perl(tmp->clone);				delete_pool_handle(tmp,inst);				spare--;				break;			}		}	}	/*	 * If the clone have reached max_request_per_clone clean it.	 */	if (inst->perl_pool->max_request_per_clone > 0 ) {			if (handle->request_count > inst->perl_pool->max_request_per_clone) {				rlm_destroy_perl(handle->clone);				delete_pool_handle(handle,inst);		}	}	/*	 * Hurry Up :)	 */	MUTEX_UNLOCK(&inst->perl_pool->mutex);	return 0;}static int init_pool (CONF_SECTION *conf, PERL_INST *inst) {	POOL_HANDLE 	*handle;	int t;	PERL_POOL	*pool;	pool = rad_malloc(sizeof(PERL_POOL));	memset(pool,0,sizeof(PERL_POOL));	inst->perl_pool = pool;	MUTEX_INIT(&pool->mutex);	/*	 * Read The Config	 *	 */	cf_section_parse(conf,pool,pool_conf);	inst->perl_pool = pool;	inst->perl_pool->detach = no;	for(t = 0;t < inst->perl_pool->start_clones ;t++){		if ((handle = pool_grow(inst)) == NULL) {			return -1;		}	}	return 1;}#endif/* *	Do any per-module initialization.  e.g. set up connections *	to external databases, read configuration files, set up *	dictionary entries, etc. * *	Try to avoid putting too much stuff in here - it's better to *	do it in instantiate() where it is not global. *	I use one global interpetator to make things more fastest for *	Threading env I clone new perl from this interp. */static int perl_init(void){	return 0;}static void xs_init(pTHX){	char *file = __FILE__;	/* DynaLoader is a special case */	newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);}/* * * This is wrapper for radlog * Now users can call radiusd::radlog(level,msg) wich is the same * calling radlog from C code. * Boyan */static XS(XS_radiusd_radlog){       dXSARGS;       if (items !=2)	       croak("Usage: radiusd::radlog(level, message)");       {	       int     level;	       char    *msg;	       level = (int) SvIV(ST(0));	       msg   = (char *) SvPV(ST(1), PL_na);	       /*		*	Because 'msg' is a 'char *', we don't want '%s', etc.		*	in it to give us printf-style vulnerabilities.		*/	       radlog(level, "rlm_perl: %s", msg);	}       XSRETURN_NO;}/* * The xlat function */static int perl_xlat(void *instance, REQUEST *request, char *fmt, char * out,		     size_t freespace, RADIUS_ESCAPE_STRING func){	PERL_INST	*inst= (PERL_INST *) instance;	PerlInterpreter *perl;	char		params[1024], *ptr, *tmp;	int		count, ret=0;	STRLEN		n_a;	/*	 * Do an xlat on the provided string (nice recursive operation).	*/	if (!radius_xlat(params, sizeof(params), fmt, request, func)) {		radlog(L_ERR, "rlm_perl: xlat failed.");		return 0;	}#ifndef USE_ITHREADS	perl = inst->perl;#endif#ifdef USE_ITHREADS	POOL_HANDLE	*handle;	if ((handle = pool_pop(instance)) == NULL) {		return 0;	}	perl = handle->clone;	radlog(L_DBG,"Found a interpetator 0x%lx",(unsigned long) perl);	{	dTHXa(perl);	}#endif	PERL_SET_CONTEXT(perl);	{	dSP;	ENTER;SAVETMPS;	ptr = strtok(params, " ");	PUSHMARK(SP);	while (ptr != NULL) {		XPUSHs(sv_2mortal(newSVpv(ptr,0)));		ptr = strtok(NULL, " ");	}	PUTBACK;	count = call_pv(inst->func_xlat, G_SCALAR | G_EVAL);	SPAGAIN;	if (SvTRUE(ERRSV)) {		radlog(L_ERR, "rlm_perl: perl_xlat exit %s\n",		       SvPV(ERRSV,n_a));		POPs ;	} else if (count > 0) {		tmp = POPp;		strNcpy(out,tmp,freespace);		ret = strlen(out);		radlog(L_DBG,"rlm_perl: Len is %d , out is %s freespace is %d",		       ret, out,freespace);	}	PUTBACK ;	FREETMPS ;	LEAVE ;	}#ifdef USE_ITHREADS	pool_release(handle, instance);#endif	return ret;}/* *	Do any per-module initialization that is separate to each *	configured instance of the module.  e.g. set up connections *	to external databases, read configuration files, set up *	dictionary entries, etc. * *	If configuration information is given in the config section *	that must be referenced in later calls, store a handle to it *	in *instance otherwise put a null pointer there. * *	Boyan: *	Setup a hashes wich we will use later *	parse a module and give him a chance to live * */static int perl_instantiate(CONF_SECTION *conf, void **instance){	PERL_INST       *inst = (PERL_INST *) instance;	HV		*rad_reply_hv;	HV		*rad_check_hv;	HV		*rad_request_hv;	HV		*rad_request_proxy_hv;	HV		*rad_request_proxy_reply_hv;	AV		*end_AV;	char *embed[4], *xlat_name;	int exitstatus = 0, argc=0;	/*	 *	Set up a storage area for instance data	 */	inst = rad_malloc(sizeof(PERL_INST));	memset(inst, 0, sizeof(PERL_INST));	/*	 *	If the configuration parameters can't be parsed, then	 *	fail.	 */	if (cf_section_parse(conf, inst, module_config) < 0) {		free(inst);		return -1;	}	embed[0] = NULL;	if (inst->perl_flags) {		embed[1] = inst->perl_flags;		embed[2] = inst->module;		embed[3] = "0";		argc = 4;	} else {		embed[1] = inst->module;		embed[2] = "0";		argc = 3;	}#ifdef USE_ITHREADS	inst->perl = interp;		if ((inst->perl = perl_alloc()) == NULL) {		radlog(L_DBG, "rlm_perl: No memory for allocating new perl !");		return (-1);	}	perl_construct(inst->perl);	PL_perl_destruct_level = 2;	{	dTHXa(inst->perl);	}	PERL_SET_CONTEXT(inst->perl);#else	if ((inst->perl = perl_alloc()) == NULL) {		radlog(L_ERR, "rlm_perl: No memory for allocating new perl !");		return -1;	}	perl_construct(inst->perl);#endif#if PERL_REVISION >= 5 && PERL_VERSION >=8	PL_exit_flags |= PERL_EXIT_DESTRUCT_END;#endif	exitstatus = perl_parse(inst->perl, xs_init, argc, embed, NULL);	end_AV = PL_endav;	PL_endav = Nullav;	if(!exitstatus) {		exitstatus = perl_run(inst->perl);	} else {		radlog(L_ERR,"rlm_perl: perl_parse failed: %s not found or has syntax errors. \n", inst->module);		return (-1);	}	PL_endav = end_AV;        newXS("radiusd::radlog",XS_radiusd_radlog, "rlm_perl.c");	rad_reply_hv = newHV();	rad_check_hv = newHV();	rad_request_hv = newHV();	rad_request_proxy_hv = newHV();	rad_request_proxy_reply_hv = newHV();	rad_reply_hv = get_hv("RAD_REPLY",1);        rad_check_hv = get_hv("RAD_CHECK",1);        rad_request_hv = get_hv("RAD_REQUEST",1);	rad_request_proxy_hv = get_hv("RAD_REQUEST_PROXY",1);	rad_request_proxy_reply_hv = get_hv("RAD_REQUEST_PROXY_REPLY",1);	xlat_name = cf_section_name2(conf);	if (xlat_name == NULL)		xlat_name = cf_section_name1(conf);	if (xlat_name){		inst->xlat_name = strdup(xlat_name);		xlat_register(xlat_name, perl_xlat, inst);	}#ifdef USE_ITHREADS	if ((init_pool(conf, inst)) == -1) {		radlog(L_ERR,"Couldn't init a pool of perl clones. Exiting");		return -1;	}#endif	*instance = inst;	return 0;}/* *  	get the vps and put them in perl hash *  	If one VP have multiple values it is added as array_ref *  	Example for this is Cisco-AVPair that holds multiple values. *  	Which will be available as array_ref in $RAD_REQUEST{'Cisco-AVPair'} */static void perl_store_vps(VALUE_PAIR *vp, HV *rad_hv){        VALUE_PAIR	*nvp, *vpa, *vpn;	AV		*av;	char            buffer[1024];	int		attr, len;	hv_undef(rad_hv);	nvp = paircopy(vp);	while (nvp != NULL) {		attr = nvp->attribute;		vpa = paircopy2(nvp,attr);		if (vpa->next) {			av = newAV();			vpn = vpa;			while (vpn) {				len = vp_prints_value(buffer, sizeof(buffer),						vpn, FALSE);				av_push(av, newSVpv(buffer, len));				vpn = vpn->next;			}			hv_store(rad_hv, nvp->name, strlen(nvp->name),					newRV_noinc((SV *) av), 0);		} else {			len = vp_prints_value(buffer, sizeof(buffer),					vpa, FALSE);			hv_store(rad_hv, vpa->name, strlen(vpa->name),					newSVpv(buffer, len), 0);		}		pairfree(&vpa);		vpa = nvp; while ((vpa != NULL) && (vpa->attribute == attr))			vpa = vpa->next;		pairdelete(&nvp, attr);		nvp = vpa;

⌨️ 快捷键说明

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