--- /dev/null
+/*
+ * rlm_acctlog.c
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2006 Suntel Communications - www.suntel.com.tr
+ *
+ * Tuyan Ozipek
+ * Peter Nixon
+ */
+
+
+#include <freeradius-devel/autoconf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/conffile.h>
+
+static const char rcsid[] = "$Id";
+
+typedef struct rlm_acctlog_t {
+ char *acctstart;
+ char *acctstop;
+ char *acctupdate;
+ char *accton;
+ char *acctoff;
+
+} rlm_acctlog_t;
+
+static const CONF_PARSER module_config[] = {
+ { "acctlog_update", PW_TYPE_STRING_PTR, offsetof(rlm_acctlog_t, acctupdate), NULL, ""},
+ { "acctlog_start", PW_TYPE_STRING_PTR, offsetof(rlm_acctlog_t, acctstart), NULL, ""},
+ { "acctlog_stop", PW_TYPE_STRING_PTR, offsetof(rlm_acctlog_t, acctstop), NULL, ""},
+ { "acctlog_on", PW_TYPE_STRING_PTR, offsetof(rlm_acctlog_t, accton), NULL, ""},
+ { "acctlog_off", PW_TYPE_STRING_PTR, offsetof(rlm_acctlog_t, acctoff), NULL, ""},
+ { NULL, -1, 0, NULL, NULL } /* end the list */
+};
+
+
+static int acctlog_detach(void *instance)
+{
+ rlm_acctlog_t *inst = instance;
+
+ free(inst->acctupdate);
+ free(inst->acctstart);
+ free(inst->acctstop);
+ free(inst->accton);
+ free(inst->acctoff);
+
+ free(inst);
+ return 0;
+}
+
+static int acctlog_instantiate(CONF_SECTION *conf, void **instance)
+{
+ rlm_acctlog_t *inst;
+
+ inst = rad_malloc(sizeof(*inst));
+ memset(inst, 0, sizeof(*inst));
+
+ if (cf_section_parse(conf, inst, module_config) < 0) {
+ acctlog_detach(inst);
+ return -1;
+ }
+
+ *instance = inst;
+
+ return 0;
+
+}
+
+static int do_acctlog_acct(void *instance, REQUEST *request)
+{
+ rlm_acctlog_t *inst;
+ VALUE_PAIR *pair;
+
+ char logstr[MAX_STRING_LEN];
+ int acctstatustype = 0;
+
+
+ inst = (rlm_acctlog_t*) instance;
+
+ if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) != NULL) {
+ acctstatustype = pair->lvalue;
+ } else {
+ radius_xlat(logstr, sizeof(logstr), "packet has no accounting status type. [user '%{User-Name}', nas '%{NAS-IP-Address}']", request, NULL);
+ radlog(L_ERR, "rlm_acctlog (%s)", logstr);
+ return RLM_MODULE_INVALID;
+ }
+
+ switch (acctstatustype) {
+ case PW_STATUS_START:
+ radius_xlat(logstr, sizeof(logstr), inst->acctstart, request, NULL);
+ break;
+ case PW_STATUS_STOP:
+ radius_xlat(logstr, sizeof(logstr), inst->acctstop, request, NULL);
+ break;
+ case PW_STATUS_ALIVE:
+ radius_xlat(logstr, sizeof(logstr), inst->acctupdate, request, NULL);
+ break;
+ case PW_STATUS_ACCOUNTING_ON:
+ radius_xlat(logstr, sizeof(logstr), inst->accton, request, NULL);
+ break;
+ case PW_STATUS_ACCOUNTING_OFF:
+ radius_xlat(logstr, sizeof(logstr), inst->acctoff, request, NULL);
+ break;
+
+ }
+
+ if (strlen(logstr))
+ radlog(L_INFO,"%s", logstr);
+
+ return RLM_MODULE_OK;
+}
+
+/*
+ * Externally visible module definition.
+ */
+module_t rlm_acctlog = {
+ RLM_MODULE_INIT,
+ "acctlog",
+ RLM_TYPE_THREAD_SAFE, /* type */
+ acctlog_instantiate, /* instantiation */
+ acctlog_detach, /* detach */
+ {
+ NULL, /* authentication */
+ NULL, /* authorization */
+ NULL, /* preaccounting */
+ do_acctlog_acct, /* accounting */
+ NULL, /* checksimul */
+ NULL, /* pre-proxy */
+ NULL, /* post-proxy */
+ NULL /* post-auth */
+ },
+};
+