/* * acct.c Accounting routines. * * Version: $Id: acct.c,v 1.28 2003/04/10 18:09:03 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 2000 The FreeRADIUS server project * Copyright 2000 Miquel van Smoorenburg * Copyright 2000 Alan DeKok * Copyright 2000 Alan Curry */ static const char rcsid[] = "$Id: acct.c,v 1.28 2003/04/10 18:09:03 aland Exp $"; #include "autoconf.h" #include "libradius.h" #include #include #include "radiusd.h" #include "modules.h" /* * rad_accounting: call modules. * * The return value of this function isn't actually used right now, so * it's not entirely clear if it is returning the right things. --Pac. */ int rad_accounting(REQUEST *request) { int reply = RLM_MODULE_OK; if (!request->proxy) { /* Only need to do this once, before proxying */ char *exec_program; int exec_wait; VALUE_PAIR *vp; int rcode; int acct_type = 0; reply = module_preacct(request); if (reply != RLM_MODULE_NOOP && reply != RLM_MODULE_OK && reply != RLM_MODULE_UPDATED) return reply; /* * Do accounting, ONLY the first time through. * This is to ensure that we log the packet * immediately, even if the proxy never does. */ vp = pairfind(request->config_items, PW_ACCT_TYPE); if (vp) acct_type = vp->lvalue; reply = module_accounting(acct_type,request); /* * See if we need to execute a program. * FIXME: somehow cache this info, and only execute the * program when we receive an Accounting-START packet. * Only at that time we know dynamic IP etc. */ exec_program = NULL; exec_wait = 0; if ((vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM)) != NULL) { exec_wait = 0; exec_program = strdup((char *)vp->strvalue); pairdelete(&request->reply->vps, PW_EXEC_PROGRAM); } if ((vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM_WAIT)) != NULL) { exec_wait = 1; exec_program = strdup((char *)vp->strvalue); pairdelete(&request->reply->vps, PW_EXEC_PROGRAM_WAIT); } /* * If we want to exec a program, but wait for it, * do it first before sending the reply, or * proxying the packet. * * If we're NOT waiting, then also do this now, but * don't check the return code. */ if (exec_program) { /* * Wait for the answer. * Don't look for a user message. * Do look for returned VP's. */ rcode = radius_exec_program(exec_program, request, exec_wait, NULL, 0, request->packet->vps, &vp); free(exec_program); /* * Always add the value-pairs to the reply. * * If we're not waiting, then the pairs * will be empty, so this won't matter. */ pairmove(&request->reply->vps, &vp); pairfree(&vp); if (exec_wait) { if (rcode != 0) { return reply; } } } /* * Maybe one of the preacct modules has decided * that a proxy should be used. If so, get out of * here and send the proxied packet, but ONLY if * there isn't one already... */ if (pairfind(request->config_items, PW_PROXY_TO_REALM)) { return reply; } } /* * We get here IF we're not proxying, OR if we've * received the accounting reply from the end server, * THEN we can reply to the NAS. */ if (reply == RLM_MODULE_NOOP || reply == RLM_MODULE_OK || reply == RLM_MODULE_UPDATED) { /* * Now send back an ACK to the NAS. */ request->reply->code = PW_ACCOUNTING_RESPONSE; } return reply; }