import from branch_1_1:
[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/autoconf.h>
30 #include <freeradius-devel/radiusd.h>
31 #include <freeradius-devel/modules.h>
32
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          *      Run the modules only once, before proxying.
45          */
46         if (!request->proxy) {
47                 VALUE_PAIR      *vp;
48                 int             acct_type = 0;
49
50                 result = module_preacct(request);
51                 switch (result) {
52                         /*
53                          *      The module has a number of OK return codes.
54                          */
55                         case RLM_MODULE_NOOP:
56                         case RLM_MODULE_OK:
57                         case RLM_MODULE_UPDATED:
58                                 break;
59                         /*
60                          *      The module handled the request, stop here.
61                          */
62                         case RLM_MODULE_HANDLED:
63                                 return result;
64                         /*
65                          *      The module failed, or said the request is
66                          *      invalid, therefore we stop here.
67                          */
68                         case RLM_MODULE_FAIL:
69                         case RLM_MODULE_INVALID:
70                         case RLM_MODULE_NOTFOUND:
71                         case RLM_MODULE_REJECT:
72                         case RLM_MODULE_USERLOCK:
73                         default:
74                                 return result;
75                 }
76
77                 /*
78                  *      Do the data storage before proxying. This is to ensure
79                  *      that we log the packet, even if the proxy never does.
80                  */
81                 vp = pairfind(request->config_items, PW_ACCT_TYPE);
82                 if (vp) {
83                         DEBUG2("  Found Acct-Type %s", vp->vp_strvalue);
84                         acct_type = vp->lvalue;
85                 }
86                 result = module_accounting(acct_type, request);
87                 switch (result) {
88                         /*
89                          *      In case the accounting module returns FAIL,
90                          *      it's still useful to send the data to the
91                          *      proxy.
92                          */
93                         case RLM_MODULE_FAIL:
94                         case RLM_MODULE_NOOP:
95                         case RLM_MODULE_OK:
96                         case RLM_MODULE_UPDATED:
97                                 break;
98                         /*
99                          *      The module handled the request, don't reply.
100                          */
101                         case RLM_MODULE_HANDLED:
102                                 return result;
103                         /*
104                          *      Neither proxy, nor reply to invalid requests.
105                          */
106                         case RLM_MODULE_INVALID:
107                         case RLM_MODULE_NOTFOUND:
108                         case RLM_MODULE_REJECT:
109                         case RLM_MODULE_USERLOCK:
110                         default:
111                                 return result;
112                 }
113
114                 /*
115                  *      Maybe one of the preacct modules has decided
116                  *      that a proxy should be used.
117                  */
118                 if ((vp = pairfind(request->config_items, PW_PROXY_TO_REALM))) {
119                         REALM *realm;
120
121                         /*
122                          *      Check whether Proxy-To-Realm is
123                          *      a LOCAL realm.
124                          */
125                         realm = realm_find(vp->vp_strvalue, TRUE);
126                         if (realm != NULL &&
127                             realm->acct_ipaddr.af == AF_INET &&
128                             realm->acct_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)) {
129                                 DEBUG("rad_accounting: Cancelling proxy to realm %s, as it is a LOCAL realm.", realm->realm);
130                                 pairdelete(&request->config_items, PW_PROXY_TO_REALM);
131                         } else {
132                                 /*
133                                  *      Don't reply to the NAS now because
134                                  *      we have to send the proxied packet
135                                  *      before that.
136                                  */
137                                 return result;
138                         }
139                 }
140         }
141
142         /*
143          *      We get here IF we're not proxying, OR if we've
144          *      received the accounting reply from the end server,
145          *      THEN we can reply to the NAS.
146          *      If the accounting module returns NOOP, the data
147          *      storage did not succeed, so radiusd should not send
148          *      Accounting-Response.
149          */
150         switch (result) {
151                 /*
152                  *      Send back an ACK to the NAS.
153                  */
154                 case RLM_MODULE_OK:
155                 case RLM_MODULE_UPDATED:
156                         request->reply->code = PW_ACCOUNTING_RESPONSE;
157                         break;
158                 /*
159                  *      The module handled the request, don't reply.
160                  */
161                 case RLM_MODULE_HANDLED:
162                         break;
163                 /*
164                  *      Failed to log or to proxy the accounting data,
165                  *      therefore don't reply to the NAS.
166                  */
167                 case RLM_MODULE_FAIL:
168                 case RLM_MODULE_INVALID:
169                 case RLM_MODULE_NOOP:
170                 case RLM_MODULE_NOTFOUND:
171                 case RLM_MODULE_REJECT:
172                 case RLM_MODULE_USERLOCK:
173                 default:
174                         break;
175         }
176         return result;
177 }