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

📄 rlm_perl.c

📁 新的radius程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * rlm_perl.c * * Version:    $Id: rlm_perl.c,v 1.13.4.8 2007/01/26 09:38:38 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 2002  The FreeRADIUS server project * Copyright 2002  Boian Jordanov <bjordanov@orbitel.bg> */#include "autoconf.h"#include "libradius.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include "radiusd.h"#include "modules.h"#include "conffile.h"#ifdef DEBUG#undef DEBUG#endif#ifdef INADDR_ANY#undef INADDR_ANY#endif#include <EXTERN.h>#include <perl.h>#include <XSUB.h>#include <dlfcn.h>#include <semaphore.h>#ifdef __APPLE__extern char **environ;#endifstatic const char rcsid[] = "$Id: rlm_perl.c,v 1.13.4.8 2007/01/26 09:38:38 aland Exp $";#ifdef USE_ITHREADS/* * Pool of Perl's clones (genetically cloned) ;) * */typedef struct pool_handle {	struct pool_handle	*next;	struct pool_handle	*prev;	enum {busy, idle}	status;	unsigned int		request_count;	PerlInterpreter	 	*clone;	perl_mutex		lock;} POOL_HANDLE;typedef struct PERL_POOL {	POOL_HANDLE	*head;	POOL_HANDLE	*tail;	int		current_clones;	int		active_clones;	int		max_clones;	int		start_clones;	int		min_spare_clones;	int		max_spare_clones;	int		max_request_per_clone;	int		cleanup_delay;	enum {yes,no}	detach;	perl_mutex	mutex;	time_t		time_when_last_added;} PERL_POOL;#endif/* *	Define a structure for our module configuration. * *	These variables do not need to be in a structure, but it's *	a lot cleaner to do so, and a pointer to the structure can *	be used as the instance handle. */typedef struct perl_inst {	/* Name of the perl module */	char	*module;	/* Name of the functions for each module method */	char	*func_authorize;	char	*func_authenticate;	char	*func_accounting;	char	*func_start_accounting;	char	*func_stop_accounting;	char	*func_preacct;	char	*func_checksimul;	char	*func_detach;	char	*func_xlat;	char	*func_pre_proxy;	char	*func_post_proxy;	char	*func_post_auth;	char	*xlat_name;	char	*perl_flags;	PerlInterpreter *perl;#ifdef USE_ITHREADS	PERL_POOL	*perl_pool;#endif} PERL_INST;/* *	A mapping of configuration file names to internal variables. * *	Note that the string is dynamically allocated, so it MUST *	be freed.  When the configuration file parse re-reads the string, *	it free's the old one, and strdup's the new one, placing the pointer *	to the strdup'd string into 'config.string'.  This gets around *	buffer over-flows. */static const CONF_PARSER module_config[] = {	{ "module",  PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,module), NULL,  "module"},	{ "func_authorize", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_authorize), NULL, "authorize"},	{ "func_authenticate", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_authenticate), NULL, "authenticate"},	{ "func_accounting", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_accounting), NULL, "accounting"},	{ "func_preacct", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_preacct), NULL, "preacct"},	{ "func_checksimul", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_checksimul), NULL, "checksimul"},	{ "func_detach", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_detach), NULL, "detach"},	{ "func_xlat", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_xlat), NULL, "xlat"},	{ "func_pre_proxy", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_pre_proxy), NULL, "pre_proxy"},	{ "func_post_proxy", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_post_proxy), NULL, "post_proxy"},	{ "func_post_auth", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_post_auth), NULL, "post_auth"},	{ "perl_flags", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,perl_flags), NULL, NULL},	{ "func_start_accounting", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_start_accounting), NULL, NULL},	{ "func_stop_accounting", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_stop_accounting), NULL, NULL},	{ NULL, -1, 0, NULL, NULL }		/* end the list */};/* * man perlembed */EXTERN_C void boot_DynaLoader(pTHX_ CV* cv);#ifdef USE_ITHREADS/* *	We use one perl to clone from it i.e. main boss *	We clone it for every instance if we have perl *	with -Duseithreads compiled in */static PerlInterpreter	*interp;static const CONF_PARSER pool_conf[] = {	{ "max_clones", PW_TYPE_INTEGER, offsetof(PERL_POOL, max_clones), NULL,		"32"},	{ "start_clones",PW_TYPE_INTEGER, offsetof(PERL_POOL, start_clones), NULL,		"5"},	{ "min_spare_clones",PW_TYPE_INTEGER, offsetof(PERL_POOL, min_spare_clones),NULL,	"3"},	{ "max_spare_clones",PW_TYPE_INTEGER, offsetof(PERL_POOL,max_spare_clones),NULL,	"3"},	{ "cleanup_delay",PW_TYPE_INTEGER, offsetof(PERL_POOL,cleanup_delay),NULL,		"5"},	{ "max_request_per_clone",PW_TYPE_INTEGER, offsetof(PERL_POOL,max_request_per_clone),NULL,	"0"},	{ NULL, -1, 0, NULL, NULL }		/* end the list */};#define dl_librefs "DynaLoader::dl_librefs"#define dl_modules "DynaLoader::dl_modules"static void rlm_perl_clear_handles(pTHX){	AV *librefs = get_av(dl_librefs, FALSE);	if (librefs) {		av_clear(librefs);	}}static void **rlm_perl_get_handles(pTHX){	I32 i;	AV *librefs = get_av(dl_librefs, FALSE);	AV *modules = get_av(dl_modules, FALSE);	void **handles;	if (!librefs) {		radlog(L_ERR,		   "Could not get @%s for unloading.\n",		   dl_librefs);		return NULL;	}	if (!(AvFILL(librefs) >= 0)) {		return NULL;	}	handles = (void **)rad_malloc(sizeof(void *) * (AvFILL(librefs)+2));	for (i=0; i<=AvFILL(librefs); i++) {		void *handle;		SV *handle_sv = *av_fetch(librefs, i, FALSE);		if(!handle_sv) {		    radlog(L_ERR,			       "Could not fetch $%s[%d]!\n",			       dl_librefs, (int)i);		    continue;		}		handle = (void *)SvIV(handle_sv);		if (handle) {		    handles[i] = handle;		}	}	av_clear(modules);	av_clear(librefs);	handles[i] = (void *)0;	return handles;}static void rlm_perl_close_handles(void **handles){	int i;	if (!handles) {		return;	}	for (i=0; handles[i]; i++) {		radlog(L_DBG, "close 0x%lx\n", (unsigned long)handles[i]);		dlclose(handles[i]);	}	free(handles);}static PerlInterpreter *rlm_perl_clone(PerlInterpreter *perl){	PerlInterpreter *clone;	UV	clone_flags = 0;	PERL_SET_CONTEXT(perl);	clone = perl_clone(perl, clone_flags);	{		dTHXa(clone);	}#if PERL_REVISION >= 5 && PERL_VERSION <8	call_pv("CLONE",0);#endif	ptr_table_free(PL_ptr_table);	PL_ptr_table = NULL;	PERL_SET_CONTEXT(aTHX);    	rlm_perl_clear_handles(aTHX);	return clone;}static void rlm_perl_destruct(PerlInterpreter *perl){	char **orig_environ = NULL;	dTHXa(perl);	PERL_SET_CONTEXT(perl);	PL_perl_destruct_level = 2;	PL_origenviron = environ;	{		dTHXa(perl);	}	/*	 * FIXME: This shouldn't happen	 *	 */	while (PL_scopestack_ix > 1 ){		LEAVE;	}	perl_destruct(perl);	perl_free(perl);	if (orig_environ) {		environ = orig_environ;	}}static void rlm_destroy_perl(PerlInterpreter *perl){	void	**handles;	dTHXa(perl);	PERL_SET_CONTEXT(perl);	handles = rlm_perl_get_handles(aTHX);	rlm_perl_destruct(perl);	rlm_perl_close_handles(handles);}static void delete_pool_handle(POOL_HANDLE *handle, PERL_INST *inst){        POOL_HANDLE *prev;        POOL_HANDLE *next;        prev = handle->prev;        next = handle->next;        if (prev == NULL) {		inst->perl_pool->head = next;        } else {                prev->next = next;        }        if (next == NULL) {		inst->perl_pool->tail = prev;        } else {                next->prev = prev;        }	inst->perl_pool->current_clones--;	MUTEX_DESTROY(&handle->lock);	free(handle);}static void move2tail(POOL_HANDLE *handle, PERL_INST *inst){	POOL_HANDLE *prev;	POOL_HANDLE *next;	if (inst->perl_pool->head == NULL) {		handle->prev = NULL;		handle->next = NULL;		inst->perl_pool->head = handle;		inst->perl_pool->tail = handle;		return;	}	if (inst->perl_pool->tail == handle) {		return;	}	prev = handle->prev;	next = handle->next;	if ((next != NULL) ||			(prev != NULL)) {		if (next == NULL) {			return;		}		if (prev == NULL) {			inst->perl_pool->head = next;			next->prev = NULL;		} else {			prev->next = next;			next->prev = prev;		}	}	handle->next = NULL;	prev = inst->perl_pool->tail;	inst->perl_pool->tail = handle;	handle->prev = prev;	prev->next = handle;}static POOL_HANDLE *pool_grow (PERL_INST *inst) {	POOL_HANDLE *handle;	time_t	now;	if (inst->perl_pool->max_clones == inst->perl_pool->current_clones) {		return NULL;	}	if (inst->perl_pool->detach == yes ) {		return NULL;	}	handle = (POOL_HANDLE *)rad_malloc(sizeof(POOL_HANDLE));	if (!handle) {		radlog(L_ERR,"Could not find free memory for pool. Aborting");		return NULL;	}	handle->prev = NULL;	handle->next = NULL;	handle->status = idle;	handle->clone = rlm_perl_clone(inst->perl);	handle->request_count = 0;	MUTEX_INIT(&handle->lock);	inst->perl_pool->current_clones++;	move2tail(handle, inst);	now = time(NULL);	inst->perl_pool->time_when_last_added = now;	return handle;}static POOL_HANDLE *pool_pop(PERL_INST *inst){	POOL_HANDLE	*handle;	POOL_HANDLE	*found;	POOL_HANDLE	*tmp;	/*	 * Lock the pool and be fast other thread maybe	 * waiting for us to finish	 */	MUTEX_LOCK(&inst->perl_pool->mutex);	found = NULL;	for (handle = inst->perl_pool->head; handle ; handle = tmp) {		tmp = handle->next;		if (handle->status == idle){			found = handle;

⌨️ 快捷键说明

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