From: hartwick Date: Wed, 18 Oct 2000 14:16:42 +0000 (+0000) Subject: Seperate the detail file generation from rlm_files. X-Git-Tag: release_0_1_0~655 X-Git-Url: http://www.project-moonshot.org/gitweb/?a=commitdiff_plain;h=bbc02e39dd95cb235b93b3a915e835896e842dd5;p=freeradius.git Seperate the detail file generation from rlm_files. --- diff --git a/src/modules/rlm_detail/Makefile b/src/modules/rlm_detail/Makefile new file mode 100644 index 0000000..6df17e8 --- /dev/null +++ b/src/modules/rlm_detail/Makefile @@ -0,0 +1,4 @@ +TARGET = rlm_detail +SRCS = rlm_detail.c + +include ../rules.mak diff --git a/src/modules/rlm_detail/rlm_detail.c b/src/modules/rlm_detail/rlm_detail.c new file mode 100644 index 0000000..c34db34 --- /dev/null +++ b/src/modules/rlm_detail/rlm_detail.c @@ -0,0 +1,220 @@ +/* + * rlm_detail.c accounting: Write the "detail" files. + * + * Version: $Id$ + * + */ + +static const char rcsid[] = "$Id$"; + +#include "autoconf.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_MALLOC_H +# include +#endif + +#include "radiusd.h" +#include "modules.h" + +struct detail_instance { + /* detail file */ + char *detailfile; + + /* detail file permissions */ + int detailperm; +}; + +static int detail_init(void) +{ + return 0; +} + +/* + * A temporary holding area for config values to be extracted + * into, before they are copied into the instance data + */ +static struct detail_instance config; + +static CONF_PARSER module_config[] = { + { "detailfile", PW_TYPE_STRING_PTR, &config.detailfile, "%A/%n/detail" }, + { "detailperm", PW_TYPE_INTEGER, &config.detailperm, "0600" }, + { NULL, -1, NULL, NULL } +}; + +/* + * (Re-)read radiusd.conf into memory. + */ +static int detail_instantiate(CONF_SECTION *conf, void **instance) +{ + struct detail_instance *inst; + + inst = malloc(sizeof *inst); + if (!inst) { + radlog(L_ERR|L_CONS, "Out of memory\n"); + return -1; + } + + if (cf_section_parse(conf, module_config) < 0) { + free(inst); + return -1; + } + + inst->detailfile = config.detailfile; + inst->detailperm = config.detailperm; + config.detailfile = NULL; + + *instance = inst; + return 0; +} + +/* + * Accounting - write the detail files. + */ +static int detail_accounting(void *instance, REQUEST *request) +{ + int outfd; + FILE *outfp; + char nasname[128]; + char buffer[512]; + char filename[512]; + char *p; + VALUE_PAIR *pair; + uint32_t nas; + NAS *cl; + long curtime; + int ret = RLM_MODULE_OK; + + struct detail_instance *inst = instance; + + curtime = time(0); + + /* + * Find out the name of this terminal server. We try + * to find the PW_NAS_IP_ADDRESS in the naslist file. + * If that fails, we look for the originating address. + * Only if that fails we resort to a name lookup. + */ + cl = NULL; + nas = request->packet->src_ipaddr; + if ((pair = pairfind(request->packet->vps, PW_NAS_IP_ADDRESS)) != NULL) + nas = pair->lvalue; + if (request->proxy && request->proxy->src_ipaddr) + nas = request->proxy->src_ipaddr; + + if ((cl = nas_find(nas)) != NULL) { + if (cl->shortname[0]) + strcpy(nasname, cl->shortname); + else + strcpy(nasname, cl->longname); + } + + if (cl == NULL) { + ip_hostname(nasname, sizeof(nasname), nas); + } + + /* + * Create a directory for this nas. + * + * Generate the path for the detail file. Use the + * same format, but truncate at the last /. Then + * feed it through radius_xlat2() to expand the + * variables. + */ + strNcpy(filename,inst->detailfile,512); + p = rindex(filename,'/'); + if(p) *p = '\0'; + radius_xlat2(buffer,512,filename,request,request->reply->vps); + if((mkdir(buffer, 0755) == -1) && errno != EEXIST) { + radlog(L_ERR, "Detail: Couldn't create %s: %s", + buffer, strerror(errno)); + return RLM_MODULE_FAIL; + } + + /* + * Write Detail file. + * + * Generate the filename for the detail file. Use the + * radius_xlat2() function to allow for variable detail + * filenames. + */ + radius_xlat2(buffer,512,inst->detailfile,request,request->reply->vps); + if ((outfd = open(buffer, O_WRONLY|O_APPEND|O_CREAT, + inst->detailperm)) < 0) { + radlog(L_ERR, "Detail: Couldn't open file %s: %s", + buffer, strerror(errno)); + ret = RLM_MODULE_FAIL; + } else if ((outfp = fdopen(outfd, "a")) == NULL) { + radlog(L_ERR, "Detail: Couldn't open file %s: %s", + buffer, strerror(errno)); + ret = RLM_MODULE_FAIL; + close(outfd); + } else { + /* Post a timestamp */ + fputs(ctime(&curtime), outfp); + + /* Write each attribute/value to the log file */ + pair = request->packet->vps; + while (pair) { + if (pair->attribute != PW_PASSWORD) { + fputs("\t", outfp); + fprint_attr_val(outfp, pair); + fputs("\n", outfp); + } + pair = pair->next; + } + + /* + * Add non-protocol attibutes. + */ + fprintf(outfp, "\tTimestamp = %ld\n", curtime); + if (request->packet->verified) + fputs("\tRequest-Authenticator = Verified\n", outfp); + else + fputs("\tRequest-Authenticator = None\n", outfp); + fputs("\n", outfp); + fclose(outfp); + } + + return ret; +} + + +/* + * Clean up. + */ +static int detail_detach(void *instance) +{ + struct detail_instance *inst = instance; + free(inst->detailfile); + free(inst); + return 0; +} + + +/* globally exported name */ +module_t rlm_detail = { + "detail", + 0, /* type: reserved */ + detail_init, /* initialization */ + detail_instantiate, /* instantiation */ + NULL, /* authorization */ + NULL, /* authentication */ + NULL, /* preaccounting */ + detail_accounting, /* accounting */ + detail_detach, /* detach */ + NULL /* destroy */ +}; +