New build path variable
[freeradius.git] / src / main / acct.c
1 /*
2  * acct.c       Accounting routines.
3  *
4  * Version:     $Id$
5  *
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.
10  *
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.
15  *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000,2006  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>
24  */
25
26 #include <freeradius-devel/ident.h>
27 RCSID("$Id$")
28
29 #include <freeradius-devel/radiusd.h>
30 #include <freeradius-devel/modules.h>
31
32 #ifdef WITH_ACCOUNTING
33 /*
34  *      rad_accounting: call modules.
35  *
36  *      The return value of this function isn't actually used right now, so
37  *      it's not entirely clear if it is returning the right things. --Pac.
38  */
39 int rad_accounting(REQUEST *request)
40 {
41         int result = RLM_MODULE_OK;
42
43
44 #ifdef WITH_PROXY
45 #define WAS_PROXIED (request->proxy)
46 #else
47 #define WAS_PROXIED (0)
48 #endif
49
50         /*
51          *      Run the modules only once, before proxying.
52          */
53         if (!WAS_PROXIED) {
54                 VALUE_PAIR      *vp;
55                 int             acct_type = 0;
56
57                 result = module_preacct(request);
58                 switch (result) {
59                         /*
60                          *      The module has a number of OK return codes.
61                          */
62                         case RLM_MODULE_NOOP:
63                         case RLM_MODULE_OK:
64                         case RLM_MODULE_UPDATED:
65                                 break;
66                         /*
67                          *      The module handled the request, stop here.
68                          */
69                         case RLM_MODULE_HANDLED:
70                                 return result;
71                         /*
72                          *      The module failed, or said the request is
73                          *      invalid, therefore we stop here.
74                          */
75                         case RLM_MODULE_FAIL:
76                         case RLM_MODULE_INVALID:
77                         case RLM_MODULE_NOTFOUND:
78                         case RLM_MODULE_REJECT:
79                         case RLM_MODULE_USERLOCK:
80                         default:
81                                 return result;
82                 }
83
84                 /*
85                  *      Do the data storage before proxying. This is to ensure
86                  *      that we log the packet, even if the proxy never does.
87                  */
88                 vp = pairfind(request->config_items, PW_ACCT_TYPE, 0);
89                 if (vp) {
90                         DEBUG2("  Found Acct-Type %s", vp->vp_strvalue);
91                         acct_type = vp->vp_integer;
92                 }
93                 result = module_accounting(acct_type, request);
94                 switch (result) {
95                         /*
96                          *      In case the accounting module returns FAIL,
97                          *      it's still useful to send the data to the
98                          *      proxy.
99                          */
100                         case RLM_MODULE_FAIL:
101                         case RLM_MODULE_NOOP:
102                         case RLM_MODULE_OK:
103                         case RLM_MODULE_UPDATED:
104                                 break;
105                         /*
106                          *      The module handled the request, don't reply.
107                          */
108                         case RLM_MODULE_HANDLED:
109                                 return result;
110                         /*
111                          *      Neither proxy, nor reply to invalid requests.
112                          */
113                         case RLM_MODULE_INVALID:
114                         case RLM_MODULE_NOTFOUND:
115                         case RLM_MODULE_REJECT:
116                         case RLM_MODULE_USERLOCK:
117                         default:
118                                 return result;
119                 }
120
121                 /*
122                  *      Maybe one of the preacct modules has decided
123                  *      that a proxy should be used.
124                  */
125                 if ((vp = pairfind(request->config_items, PW_PROXY_TO_REALM, 0))) {
126                         REALM *realm;
127
128                         /*
129                          *      Check whether Proxy-To-Realm is
130                          *      a LOCAL realm.
131                          */
132                         realm = realm_find2(vp->vp_strvalue);
133                         if (realm && !realm->acct_pool) {
134                                 DEBUG("rad_accounting: Cancelling proxy to realm %s, as it is a LOCAL realm.", realm->name);
135                                 pairdelete(&request->config_items, PW_PROXY_TO_REALM, 0);
136                         } else {
137                                 /*
138                                  *      Don't reply to the NAS now because
139                                  *      we have to send the proxied packet
140                                  *      before that.
141                                  */
142                                 return result;
143                         }
144                 }
145         }
146
147         /*
148          *      We get here IF we're not proxying, OR if we've
149          *      received the accounting reply from the end server,
150          *      THEN we can reply to the NAS.
151          *      If the accounting module returns NOOP, the data
152          *      storage did not succeed, so radiusd should not send
153          *      Accounting-Response.
154          */
155         switch (result) {
156                 /*
157                  *      Send back an ACK to the NAS.
158                  */
159                 case RLM_MODULE_OK:
160                 case RLM_MODULE_UPDATED:
161                         request->reply->code = PW_ACCOUNTING_RESPONSE;
162                         break;
163                 /*
164                  *      The module handled the request, don't reply.
165                  */
166                 case RLM_MODULE_HANDLED:
167                         break;
168                 /*
169                  *      Failed to log or to proxy the accounting data,
170                  *      therefore don't reply to the NAS.
171                  */
172                 case RLM_MODULE_FAIL:
173                 case RLM_MODULE_INVALID:
174                 case RLM_MODULE_NOOP:
175                 case RLM_MODULE_NOTFOUND:
176                 case RLM_MODULE_REJECT:
177                 case RLM_MODULE_USERLOCK:
178                 default:
179                         break;
180         }
181         return result;
182 }
183 #endif