Seperate the detail file generation from rlm_files.
authorhartwick <hartwick>
Wed, 18 Oct 2000 14:16:42 +0000 (14:16 +0000)
committerhartwick <hartwick>
Wed, 18 Oct 2000 14:16:42 +0000 (14:16 +0000)
src/modules/rlm_detail/Makefile [new file with mode: 0644]
src/modules/rlm_detail/rlm_detail.c [new file with mode: 0644]

diff --git a/src/modules/rlm_detail/Makefile b/src/modules/rlm_detail/Makefile
new file mode 100644 (file)
index 0000000..6df17e8
--- /dev/null
@@ -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 (file)
index 0000000..c34db34
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * rlm_detail.c        accounting:    Write the "detail" files.
+ *
+ * Version:    $Id$
+ *
+ */
+
+static const char rcsid[] = "$Id$";
+
+#include       "autoconf.h"
+
+#include       <sys/stat.h>
+#include       <sys/types.h>
+#include       <netinet/in.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <errno.h>
+#include       <time.h>
+#include       <ctype.h>
+#include       <fcntl.h>
+#include       <unistd.h>
+
+#if HAVE_MALLOC_H
+#  include     <malloc.h>
+#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 */
+};
+