2 * acct.c Accounting routines.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Copyright 2000 The FreeRADIUS server project
21 * Copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
22 * Copyright 2000 Alan DeKok <aland@ox.org>
23 * Copyright 2000 Alan Curry <pacman@world.std.com>
26 static const char rcsid[] = "$Id$";
38 * rad_accounting: call modules.
40 * The return value of this function isn't actually used right now, so
41 * it's not entirely clear if it is returning the right things. --Pac.
43 int rad_accounting(REQUEST *request)
45 int reply = RLM_MODULE_OK;
47 if (!request->proxy) { /* Only need to do this once, before proxying */
54 reply = module_preacct(request);
55 if (reply != RLM_MODULE_NOOP &&
56 reply != RLM_MODULE_OK &&
57 reply != RLM_MODULE_UPDATED)
61 * Do accounting, ONLY the first time through.
62 * This is to ensure that we log the packet
63 * immediately, even if the proxy never does.
65 vp = pairfind(request->config_items, PW_ACCT_TYPE);
67 acct_type = vp->lvalue;
68 reply = module_accounting(acct_type,request);
71 * See if we need to execute a program.
72 * FIXME: somehow cache this info, and only execute the
73 * program when we receive an Accounting-START packet.
74 * Only at that time we know dynamic IP etc.
78 if ((vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM)) != NULL) {
80 exec_program = strdup((char *)vp->strvalue);
81 pairdelete(&request->reply->vps, PW_EXEC_PROGRAM);
84 if ((vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM_WAIT)) != NULL) {
86 exec_program = strdup((char *)vp->strvalue);
87 pairdelete(&request->reply->vps, PW_EXEC_PROGRAM_WAIT);
91 * If we want to exec a program, but wait for it,
92 * do it first before sending the reply, or
93 * proxying the packet.
95 * If we're NOT waiting, then also do this now, but
96 * don't check the return code.
100 * Wait for the answer.
101 * Don't look for a user message.
102 * Do look for returned VP's.
104 rcode = radius_exec_program(exec_program, request,
106 request->packet->vps, &vp, 1);
110 * Always add the value-pairs to the reply.
112 * If we're not waiting, then the pairs
113 * will be empty, so this won't matter.
115 pairmove(&request->reply->vps, &vp);
126 * Maybe one of the preacct modules has decided
127 * that a proxy should be used.
129 if ((vp = pairfind(request->config_items, PW_PROXY_TO_REALM))) {
133 * Check whether Proxy-To-Realm is
136 realm = realm_find(vp->strvalue, TRUE);
138 realm->ipaddr.af == AF_INET &&
139 realm->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)) {
140 DEBUG("rad_accounting: Cancelling proxy to realm %s, as it is a LOCAL realm.", realm->realm);
141 pairdelete(&request->config_items, PW_PROXY_TO_REALM);
144 * Don't reply to the NAS now because
145 * we have to send the proxied packet.
153 * We get here IF we're not proxying, OR if we've
154 * received the accounting reply from the end server,
155 * THEN we can reply to the NAS.
156 * If the accounting module returns NOOP, the data
157 * storage did not succeed, so radiusd should not send
158 * Accounting-Response.
160 if (reply == RLM_MODULE_OK ||
161 reply == RLM_MODULE_UPDATED) {
164 * Now send back an ACK to the NAS.
166 request->reply->code = PW_ACCOUNTING_RESPONSE;