Massively cleaned up #include's, so they're in a consistent
[freeradius.git] / src / main / acct.c
index f6040c8..367f118 100644 (file)
  *
  *   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
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  * Copyright 2000  Alan Curry <pacman@world.std.com>
  */
 
-static const char rcsid[] = "$Id$";
-
-#include "autoconf.h"
-#include "libradius.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "radiusd.h"
-#include "modules.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 /*
  *     rad_accounting: call modules.
@@ -43,94 +37,102 @@ static const char rcsid[] = "$Id$";
  */
 int rad_accounting(REQUEST *request)
 {
-       int             reply = RLM_MODULE_OK;
+       int result = RLM_MODULE_OK;
 
-       if (!request->proxy) { /* Only need to do this once, before proxying */
-               char            *exec_program;
-               int             exec_wait;
+       /*
+        *      Run the modules only once, before proxying.
+        */
+       if (!request->proxy) {
                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;
+               result = module_preacct(request);
+               switch (result) {
+                       /*
+                        *      The module has a number of OK return codes.
+                        */
+                       case RLM_MODULE_NOOP:
+                       case RLM_MODULE_OK:
+                       case RLM_MODULE_UPDATED:
+                               break;
+                       /*
+                        *      The module handled the request, stop here.
+                        */
+                       case RLM_MODULE_HANDLED:
+                               return result;
+                       /*
+                        *      The module failed, or said the request is
+                        *      invalid, therefore we stop here.
+                        */
+                       case RLM_MODULE_FAIL:
+                       case RLM_MODULE_INVALID:
+                       case RLM_MODULE_NOTFOUND:
+                       case RLM_MODULE_REJECT:
+                       case RLM_MODULE_USERLOCK:
+                       default:
+                               return result;
+               }
 
                /*
-                *      Do accounting, ONLY the first time through.
-                *      This is to ensure that we log the packet
-                *      immediately, even if the proxy never does.
+                *      Do the data storage before proxying. This is to ensure
+                *      that we log the packet, even if the proxy never does.
                 */
                vp = pairfind(request->config_items, PW_ACCT_TYPE);
-               if (vp)
+               if (vp) {
+                       DEBUG2("  Found Acct-Type %s", vp->vp_strvalue);
                        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) {
+               result = module_accounting(acct_type, request);
+               switch (result) {
                        /*
-                        *      Wait for the answer.
-                        *      Don't look for a user message.
-                        *      Do look for returned VP's.
+                        *      In case the accounting module returns FAIL,
+                        *      it's still useful to send the data to the
+                        *      proxy.
                         */
-                       rcode = radius_exec_program(exec_program, request,
-                                                   exec_wait, NULL, 0,
-                                                   request->packet->vps, &vp);
-                       free(exec_program);
-
+                       case RLM_MODULE_FAIL:
+                       case RLM_MODULE_NOOP:
+                       case RLM_MODULE_OK:
+                       case RLM_MODULE_UPDATED:
+                               break;
                        /*
-                        *      Always add the value-pairs to the reply.
-                        *
-                        *      If we're not waiting, then the pairs
-                        *      will be empty, so this won't matter.
+                        *      The module handled the request, don't reply.
                         */
-                       pairmove(&request->reply->vps, &vp);
-                       pairfree(&vp);
-
-                       if (exec_wait) {
-                               if (rcode != 0) {
-                                       return reply;
-                               }
-                       }
+                       case RLM_MODULE_HANDLED:
+                               return result;
+                       /*
+                        *      Neither proxy, nor reply to invalid requests.
+                        */
+                       case RLM_MODULE_INVALID:
+                       case RLM_MODULE_NOTFOUND:
+                       case RLM_MODULE_REJECT:
+                       case RLM_MODULE_USERLOCK:
+                       default:
+                               return result;
                }
 
                /*
                 *      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...
+                *      that a proxy should be used.
                 */
-               if (pairfind(request->config_items, PW_PROXY_TO_REALM)) {
-                       return reply;
+               if ((vp = pairfind(request->config_items, PW_PROXY_TO_REALM))) {
+                       REALM *realm;
+
+                       /*
+                        *      Check whether Proxy-To-Realm is
+                        *      a LOCAL realm.
+                        */
+                       realm = realm_find(vp->vp_strvalue);
+                       if (realm && !realm->acct_pool) {
+                               DEBUG("rad_accounting: Cancelling proxy to realm %s, as it is a LOCAL realm.", realm->name);
+                               pairdelete(&request->config_items, PW_PROXY_TO_REALM);
+                       } else {
+                               /*
+                                *      Don't reply to the NAS now because
+                                *      we have to send the proxied packet
+                                *      before that.
+                                */
+                               return result;
+                       }
                }
        }
 
@@ -142,15 +144,31 @@ int rad_accounting(REQUEST *request)
         *      storage did not succeed, so radiusd should not send
         *      Accounting-Response.
         */
-       if (reply == RLM_MODULE_OK ||
-           reply == RLM_MODULE_UPDATED) {
-
+       switch (result) {
+               /*
+                *      Send back an ACK to the NAS.
+                */
+               case RLM_MODULE_OK:
+               case RLM_MODULE_UPDATED:
+                       request->reply->code = PW_ACCOUNTING_RESPONSE;
+                       break;
                /*
-                *      Now send back an ACK to the NAS.
+                *      The module handled the request, don't reply.
                 */
-               request->reply->code = PW_ACCOUNTING_RESPONSE;
+               case RLM_MODULE_HANDLED:
+                       break;
+               /*
+                *      Failed to log or to proxy the accounting data,
+                *      therefore don't reply to the NAS.
+                */
+               case RLM_MODULE_FAIL:
+               case RLM_MODULE_INVALID:
+               case RLM_MODULE_NOOP:
+               case RLM_MODULE_NOTFOUND:
+               case RLM_MODULE_REJECT:
+               case RLM_MODULE_USERLOCK:
+               default:
+                       break;
        }
-
-       return reply;
+       return result;
 }
-