Enable building WITHOUT_ACCOUNTING
[freeradius.git] / src / modules / rlm_radutmp / rlm_radutmp.c
index 583ce23..65fe1c0 100644 (file)
  *   along with this program; if not, write to the Free Software
  *   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
  * FIXME add copyrights
  */
 
-#include       <freeradius-devel/autoconf.h>
-
-#include       <sys/types.h>
-#include       <stdio.h>
-#include       <string.h>
-#include       <stdlib.h>
-#include       <unistd.h>
-#include       <fcntl.h>
-#include       <time.h>
-#include       <errno.h>
-#include        <limits.h>
-
-#include "config.h"
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
 
 #include       <freeradius-devel/radiusd.h>
 #include       <freeradius-devel/radutmp.h>
 #include       <freeradius-devel/modules.h>
 #include       <freeradius-devel/rad_assert.h>
 
+#include       <fcntl.h>
+#include        <limits.h>
+
+#include "config.h"
+
 #define LOCK_LEN sizeof(struct radutmp)
 
 static const char porttypes[] = "ASITX";
@@ -114,8 +108,6 @@ static int radutmp_detach(void *instance)
                next = p->next;
                free(p);
        }
-       if (inst->filename) free(inst->filename);
-       if (inst->username) free(inst->username);
        free(inst);
        return 0;
 }
@@ -123,7 +115,7 @@ static int radutmp_detach(void *instance)
 /*
  *     Zap all users on a NAS from the radutmp file.
  */
-static int radutmp_zap(rlm_radutmp_t *inst,
+static int radutmp_zap(UNUSED rlm_radutmp_t *inst,
                       const char *filename,
                       uint32_t nasaddr,
                       time_t t)
@@ -183,6 +175,7 @@ static NAS_PORT *nas_port_find(NAS_PORT *nas_port_list, uint32_t nasaddr, unsign
 }
 
 
+#ifdef WITH_ACCOUNTING
 /*
  *     Store logins in the RADIUS utmp file.
  */
@@ -191,14 +184,10 @@ static int radutmp_accounting(void *instance, REQUEST *request)
        struct radutmp  ut, u;
        VALUE_PAIR      *vp;
        int             status = -1;
-       uint32_t        nas_address = 0;
-       uint32_t        framed_address = 0;
        int             protocol = -1;
        time_t          t;
        int             fd;
-       int             just_an_update = 0;
        int             port_seen = 0;
-       int             nas_port_type = 0;
        int             off;
        rlm_radutmp_t   *inst = instance;
        char            buffer[256];
@@ -216,11 +205,11 @@ static int radutmp_accounting(void *instance, REQUEST *request)
        /*
         *      Which type is this.
         */
-       if ((vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) == NULL) {
+       if ((vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE, 0)) == NULL) {
                radlog(L_ERR, "rlm_radutmp: No Accounting-Status-Type record.");
                return RLM_MODULE_NOOP;
        }
-       status = vp->lvalue;
+       status = vp->vp_integer;
 
        /*
         *      Look for weird reboot packets.
@@ -239,10 +228,10 @@ static int radutmp_accounting(void *instance, REQUEST *request)
                int check1 = 0;
                int check2 = 0;
 
-               if ((vp = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME))
-                    == NULL || vp->lvalue == 0)
+               if ((vp = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME, 0))
+                    == NULL || vp->vp_date == 0)
                        check1 = 1;
-               if ((vp = pairfind(request->packet->vps, PW_ACCT_SESSION_ID))
+               if ((vp = pairfind(request->packet->vps, PW_ACCT_SESSION_ID, 0))
                     != NULL && vp->length == 8 &&
                     memcmp(vp->vp_strvalue, "00000000", 8) == 0)
                        check2 = 1;
@@ -264,6 +253,7 @@ static int radutmp_accounting(void *instance, REQUEST *request)
        time(&t);
        memset(&ut, 0, sizeof(ut));
        ut.porttype = 'A';
+       ut.nas_address = htonl(INADDR_NONE);
 
        /*
         *      First, find the interesting attributes.
@@ -272,22 +262,20 @@ static int radutmp_accounting(void *instance, REQUEST *request)
                switch (vp->attribute) {
                        case PW_LOGIN_IP_HOST:
                        case PW_FRAMED_IP_ADDRESS:
-                               framed_address = vp->lvalue;
-                               ut.framed_address = vp->lvalue;
+                               ut.framed_address = vp->vp_ipaddr;
                                break;
                        case PW_FRAMED_PROTOCOL:
-                               protocol = vp->lvalue;
+                               protocol = vp->vp_integer;
                                break;
                        case PW_NAS_IP_ADDRESS:
-                               nas_address = vp->lvalue;
-                               ut.nas_address = vp->lvalue;
+                               ut.nas_address = vp->vp_ipaddr;
                                break;
                        case PW_NAS_PORT:
-                               ut.nas_port = vp->lvalue;
+                               ut.nas_port = vp->vp_integer;
                                port_seen = 1;
                                break;
                        case PW_ACCT_DELAY_TIME:
-                               ut.delay = vp->lvalue;
+                               ut.delay = vp->vp_integer;
                                break;
                        case PW_ACCT_SESSION_ID:
                                /*
@@ -308,13 +296,12 @@ static int radutmp_accounting(void *instance, REQUEST *request)
                                        sizeof(ut.session_id));
                                break;
                        case PW_NAS_PORT_TYPE:
-                               if (vp->lvalue <= 4)
-                                       ut.porttype = porttypes[vp->lvalue];
-                               nas_port_type = vp->lvalue;
+                               if (vp->vp_integer <= 4)
+                                       ut.porttype = porttypes[vp->vp_integer];
                                break;
                        case PW_CALLING_STATION_ID:
                                if(inst->callerid_ok)
-                                       strNcpy(ut.caller_id,
+                                       strlcpy(ut.caller_id,
                                                (char *)vp->vp_strvalue,
                                                sizeof(ut.caller_id));
                                break;
@@ -325,32 +312,20 @@ static int radutmp_accounting(void *instance, REQUEST *request)
         *      If we didn't find out the NAS address, use the
         *      originator's IP address.
         */
-       if (nas_address == 0) {
-               nas_address = request->packet->src_ipaddr.ipaddr.ip4addr.s_addr;
-               ut.nas_address = nas_address;
-               nas = client_name_old(&request->packet->src_ipaddr); /* MUST be a valid client */
-
-       } else if (request->packet->src_ipaddr.ipaddr.ip4addr.s_addr == nas_address) {          /* might be a client, might not be. */
-               RADCLIENT *cl;
-               
-               /*
-                *      Hack like 'client_name()', but with sane
-                *      fall-back.
-                */
-               cl = client_find_old(&request->packet->src_ipaddr);
-               if (!cl) rad_assert(0 == 1); /* WTF? */
-               if (cl->shortname && cl->shortname[0]) {
-                       nas = cl->shortname;
-               } else {
-                       nas = cl->longname;
-               }
+       if (ut.nas_address == htonl(INADDR_NONE)) {
+               ut.nas_address = request->packet->src_ipaddr.ipaddr.ip4addr.s_addr;
+               nas = request->client->shortname;
+
+       } else if (request->packet->src_ipaddr.ipaddr.ip4addr.s_addr == ut.nas_address) {               /* might be a client, might not be. */
+               nas = request->client->shortname;
+
        } else {
                /*
                 *      The NAS isn't a client, it's behind
                 *      a proxy server.  In that case, just
                 *      get the IP address.
                 */
-               nas = ip_ntoa(ip_name, nas_address);
+               nas = ip_ntoa(ip_name, ut.nas_address);
        }
 
        /*
@@ -376,17 +351,19 @@ static int radutmp_accounting(void *instance, REQUEST *request)
         *      the NAS comes up, because of issues with receiving
         *      UDP packets out of order.
         */
-       if (status == PW_STATUS_ACCOUNTING_ON && nas_address) {
+       if (status == PW_STATUS_ACCOUNTING_ON &&
+           (ut.nas_address != htonl(INADDR_NONE))) {
                radlog(L_INFO, "rlm_radutmp: NAS %s restarted (Accounting-On packet seen)",
                       nas);
-               radutmp_zap(inst, filename, nas_address, ut.time);
+               radutmp_zap(inst, filename, ut.nas_address, ut.time);
                return RLM_MODULE_OK;
        }
 
-       if (status == PW_STATUS_ACCOUNTING_OFF && nas_address) {
+       if (status == PW_STATUS_ACCOUNTING_OFF &&
+           (ut.nas_address != htonl(INADDR_NONE))) {
                radlog(L_INFO, "rlm_radutmp: NAS %s rebooted (Accounting-Off packet seen)",
                       nas);
-               radutmp_zap(inst, filename, nas_address, ut.time);
+               radutmp_zap(inst, filename, ut.nas_address, ut.time);
                return RLM_MODULE_OK;
        }
 
@@ -411,7 +388,7 @@ static int radutmp_accounting(void *instance, REQUEST *request)
        /*
         *  Copy the previous translated user name.
         */
-       strncpy(ut.login, buffer, RUT_NAMESIZE);
+       strlcpy(ut.login, buffer, RUT_NAMESIZE);
 
        /*
         *      Perhaps we don't want to store this record into
@@ -515,8 +492,6 @@ static int radutmp_accounting(void *instance, REQUEST *request)
                         *      Keep the original login time.
                         */
                        ut.time = u.time;
-                       if (u.login[0] != 0)
-                               just_an_update = 1;
                }
 
                if (lseek(fd, -(off_t)sizeof(u), SEEK_CUR) < 0) {
@@ -565,14 +540,15 @@ static int radutmp_accounting(void *instance, REQUEST *request)
                } else if (r == 0) {
                        radlog(L_ERR, "rlm_radutmp: Logout for NAS %s port %u, but no Login record",
                               nas, ut.nas_port);
-                       r = -1;
                }
        }
        close(fd);      /* and implicitely release the locks */
 
        return RLM_MODULE_OK;
 }
+#endif
 
+#ifdef WITH_SESSION_MGMT
 /*
  *     See if a user is already logged in. Sets request->simul_count to the
  *     current session count for this user and sets request->simul_mpp to 2
@@ -657,9 +633,9 @@ static int radutmp_checksimul(void *instance, REQUEST *request)
        /*
         *      Setup some stuff, like for MPP detection.
         */
-       if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS)) != NULL)
-               ipno = vp->lvalue;
-       if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) != NULL)
+       if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS, 0)) != NULL)
+               ipno = vp->vp_ipaddr;
+       if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID, 0)) != NULL)
                call_num = vp->vp_strvalue;
 
        /*
@@ -682,7 +658,7 @@ static int radutmp_checksimul(void *instance, REQUEST *request)
                        char session_id[sizeof(u.session_id) + 1];
                        char utmp_login[sizeof(u.login) + 1];
 
-                       strNcpy(session_id, u.session_id, sizeof(session_id));
+                       strlcpy(session_id, u.session_id, sizeof(session_id));
 
                        /*
                         *      The login name MAY fill the whole field,
@@ -700,7 +676,7 @@ static int radutmp_checksimul(void *instance, REQUEST *request)
                         *      and the NAS says "no", because "BOB"
                         *      is using the port.
                         */
-                       strNcpy(utmp_login, u.login, sizeof(u.login));
+                       strlcpy(utmp_login, u.login, sizeof(u.login));
 
                        /*
                         *      rad_check_ts may take seconds
@@ -752,20 +728,29 @@ static int radutmp_checksimul(void *instance, REQUEST *request)
 
        return RLM_MODULE_OK;
 }
+#endif
 
 /* globally exported name */
 module_t rlm_radutmp = {
        RLM_MODULE_INIT,
        "radutmp",
-       0,                            /* type: reserved */
+       RLM_TYPE_CHECK_CONFIG_SAFE | RLM_TYPE_HUP_SAFE,         /* type */
        radutmp_instantiate,          /* instantiation */
        radutmp_detach,               /* detach */
        {
                NULL,                 /* authentication */
                NULL,                 /* authorization */
                NULL,                 /* preaccounting */
+#ifdef WITH_ACCOUNTING
                radutmp_accounting,   /* accounting */
+#else
+               NULL,
+#endif
+#ifdef WITH_SESSION_MGMT
                radutmp_checksimul,     /* checksimul */
+#else
+               NULL,
+#endif
                NULL,                   /* pre-proxy */
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */