Logo Search packages:      
Sourcecode: netams version File versions  Download package

s_quotactl.c

/*************************************************************************
***   Authentication, authorization, accounting + firewalling package
***   Copyright 1998-2002 Anton Vinokurov <anton@netams.com>
***   Copyright 2002-2008 NeTAMS Development Team
***   This code is GPL v3
***   For latest version and more info, visit this project web page
***   located at http://www.netams.com
***
*************************************************************************/
/* $Id: s_quotactl.c,v 1.83 2009-08-01 09:23:54 anton Exp $ */

#include "netams.h"

static int initialized=0;
/////////////////////////////////////////////////////////////////////////
int cShowQuotactl (struct cli_def *cli, const char *cmd, char **argv, int argc);
/////////////////////////////////////////////////////////////////////////
//defined commands
static const  struct CMD_DB cmd_db[] = {
{ 2, 0, 0, "show",      PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL,        "shows various system parameters" },
{ 0, 2, 0, "quotactl",  PRIVILEGE_UNPRIVILEGED, MODE_EXEC, cShowQuotactl,     "quotactl status" },
{ 0, 0, 0, "quota",     PRIVILEGE_UNPRIVILEGED, MODE_QUOTACTL, cServiceProcessCfg,  NULL },
{ 3, 0, 0, "bind",      PRIVILEGE_UNPRIVILEGED, MODE_QUOTACTL, NULL,                NULL },
{ 0, 3, 0, "quota",     PRIVILEGE_UNPRIVILEGED, MODE_QUOTACTL, cServiceProcessCfg,  NULL },
{ 4, 0, 0,  "alert",    PRIVILEGE_UNPRIVILEGED, MODE_QUOTACTL, NULL,                NULL },     
{ 5, 4, 0,  "soft-reach", PRIVILEGE_UNPRIVILEGED, MODE_QUOTACTL, cServiceProcessCfg,      NULL },
{ 0, 5, 0, "user",      PRIVILEGE_UNPRIVILEGED, MODE_QUOTACTL, cServiceProcessCfg,  NULL },
{ 6, 4, 0, "hard-reach", PRIVILEGE_UNPRIVILEGED, MODE_QUOTACTL, cServiceProcessCfg, NULL },
{ 0, 6, 0, "user",      PRIVILEGE_UNPRIVILEGED, MODE_QUOTACTL, cServiceProcessCfg,  NULL },
{ 7, 4, 0, "reset-back", PRIVILEGE_UNPRIVILEGED, MODE_QUOTACTL, cServiceProcessCfg, NULL },
{ 0, 7, 0, "user",      PRIVILEGE_UNPRIVILEGED, MODE_QUOTACTL, cServiceProcessCfg,  NULL },
{ 0, 0, 0, "lookup-delay", PRIVILEGE_UNPRIVILEGED, MODE_QUOTACTL, cServiceProcessCfg,     NULL },
{ 0, 0, 0, "start",     PRIVILEGE_UNPRIVILEGED, MODE_QUOTACTL, cServiceStart,           NULL },
{ 0, 0, 0, "stop",      PRIVILEGE_UNPRIVILEGED, MODE_QUOTACTL, cServiceStop,            NULL },
{ -1, 0, 0, NULL,  0, 0, NULL, NULL }
};
/////////////////////////////////////////////////////////////////////////
// this using in quotactl service as unit representation
typedef struct qUlist {
    NetUnit *u;
    qUlist *next;
      u_char q_soft,q_viol;
} __attribute__((packed)) qUlist;
//////////////////////////////////////////////////////////////////////////
// quotactl control service functionality

typedef struct Qdef {
        char *name;
        Policy *policy;
        qstat h, d, w, m;
        qUlist *root;
        Qdef *next;

        SysPolicy sys_policy;
        oid sys_policy_perm;

} Qdef;
//////////////////////////////////////////////////////////////////////////  
class Service_Quotactl: public Service {
      public:
            Qdef *root;
            pthread_rwlock_t rwlock;
            User *soft_reach; User *hard_reach; User *reset_back;
            u_char user_soft_reach, user_hard_reach, user_reset_back;
            unsigned short delay; // in seconds
            
            Service_Quotactl();
            ~Service_Quotactl();

            void ShowCfg(struct cli_def *cli, u_char flags);
            int ProcessCfg(struct cli_def *cli, char **argv, int argc, u_char no_flag);
            void Worker();
            void Cancel();

            void SendAlert(NetUnit *u, Qdef *q, u_char dir);
};
//////////////////////////////////////////////////////////////////////////
void sQuotactlGetValue(u_char *i, char *param[], qstat *q);
//////////////////////////////////////////////////////////////////////////
Service* InitQuotactlService() {
      if(!initialized) {
            InitCliCommands(cmd_db);
            initialized = 1;
      }
      return (Service*)new Service_Quotactl();
}
//////////////////////////////////////////////////////////////////////////
Service_Quotactl::Service_Quotactl():Service(SERVICE_QUOTACTL) {
      root=NULL;
      delay=QUOTACTL_DELAY; 

      soft_reach=hard_reach=reset_back=NULL;
      user_soft_reach=user_hard_reach=user_reset_back=0;

      netams_rwlock_init(&rwlock, NULL);
}

Service_Quotactl::~Service_Quotactl() {
      time_t now = time(NULL);       

      netams_rwlock_rdlock(&Units->rwlock);

      for (Qdef *q=root; q!=NULL;) {
            for(qUlist *ql=q->root;ql!=NULL;) {
                  NetUnit *u=ql->u;
                  if (u && (u->sys_policy&q->sys_policy)) {
                        u->SetSysPolicy(q->sys_policy, REMOVE, now);
                        if(q->sys_policy_perm) u->sys_policy_perm=0;
                  }
                  qUlist *ptr=ql;
                  ptr=ql;
                  ql=ql->next;
                  aFree(ptr);
            }
            Qdef *qd=q;
            q=q->next;
            aFree(qd->name);
            aFree(qd);
        }
        netams_rwlock_unlock(&Units->rwlock);
        
      netams_rwlock_destroy(&rwlock);
}
//////////////////////////////////////////////////////////////////////////
int Service_Quotactl::ProcessCfg(struct cli_def *cli, char **param, int argc, u_char no_flag){
      Qdef *q=NULL;
      Qdef *qq=NULL;
      time_t now=time(NULL);

      netams_rwlock_wrlock(&rwlock);
      if (STREQ(param[0], "quota")) {
            for (q=root; q!=NULL; q=q->next) {
                  if (STREQ(param[1], q->name)) break;
                  qq=q;
            }

            if (q && no_flag) {
                  if(q==root) root=q->next;
                  else qq->next=q->next;
                  qUlist *ql=q->root;
                  qUlist *tmp;
                  while(ql){
                        NetUnit *u=ql->u;
                        if (u && (u->sys_policy&SP_DENY_QUOTA)) {
                              u->SetSysPolicy(SP_DENY_QUOTA, REMOVE, now);
                              if(q->sys_policy_perm) u->sys_policy_perm=0;
                              cli_error(cli, "unit %06X (%s) unbinded from quota %s",
                                    u->id, u->name?u->name:"<>", q->name);
                                }
                        tmp=ql;
                        ql=ql->next;
                        aFree(tmp);
                  }
                  cli_error(cli, "quota %s deleted", q->name);
                  aFree(q->name);
                  aFree(q); 
                  netams_rwlock_unlock(&rwlock);
                  return CLI_OK;
            }
            if (!q) {
                  if (no_flag) { 
                        cli_error(cli, "quota %s not defined", param[1]);
                        netams_rwlock_unlock(&rwlock);
                        return CLI_OK;
                  }     

                  q=(Qdef*) aMalloc(sizeof(Qdef));
                  q->name=set_string(param[1]);
                  if (!root) root=q; else qq->next=q;
                  q->next=NULL;
                  q->root=NULL;
                  cli_error(cli, "quota %s created", q->name);
            }

            for(u_char i=2; i<argc;i+=2) {
                  if (STRARG(param[i], "policy")) {
                        Policy *pol=PolicyL->getPolicy(param[i+1]);
                        if (pol) {
                              q->policy=pol;
                              cli_error(cli, "quota %s policy %s (%06X) is set",
                                    q->name, pol->name?pol->name:"<>", pol->id);
                        }
                        else
                              cli_error(cli, "quota %s policy %s is undefined", q->name, param[i+1]);
                  }
                  else if (STREQ(param[i], "set")) {
                        NetUnit *u = new NetUnit(NETUNIT_UNKNOWN);
                        u->id=0xFFFFFF;
                        SetSysPolicy(cli, u, param[i+1]);
                        q->sys_policy|=u->sys_policy;
                        q->sys_policy_perm=u->sys_policy_perm;
/*                      char tmp[128];
                        aParse(conn, "quota %s set: %s",
                              q->name,
                              GetSysPolicy(tmp, u->sys_policy, u->sys_policy_perm));
*/                      delete u;
                  }
                  else if (STRARG(param[i], "hour"))
                        sQuotactlGetValue(&i, param, &(q->h));
                  else if (STRARG(param[i], "day"))
                        sQuotactlGetValue(&i, param, &(q->d));
                  else if (STRARG(param[i], "week"))
                        sQuotactlGetValue(&i, param, &(q->w));
                  else if (STRARG(param[i], "month"))
                        sQuotactlGetValue(&i, param, &(q->m));
            } //for
      } //quota
      else if (STREQ(param[0], "bind") && STREQ(param[1], "quota") && STREQ(param[3], "to")) {
            for (Qdef *quotas=root; quotas!=NULL; quotas=quotas->next) {
                  if (STREQ(param[2], quotas->name))
                        q=quotas;
            }
            if (!q) {
                  cli_error(cli, "bind to undefined quota");
                  netams_rwlock_unlock(&rwlock);
                  return CLI_OK;
            }
            NetUnit *u; oid id;
            for(u_char i=4; i<argc; i++) {
                  qUlist *ql,*qu,*qql=NULL;
                  id=strtol(param[i], NULL, 16);
                  u=(NetUnit*)Units->getById(id);
                  if (!u) 
                        u=Units->getUnit(param[i]);
                  if (u) {
                        for (ql=q->root; ql!=NULL; ql=ql->next) {
                              if (ql->u==u) break;
                              qql=ql;
                        }
                        if(ql) { 
                              if(!no_flag) {
                                    cli_error(cli, "unit %06X (%s) is already binded with quota %s",
                                          u->id, u->name?u->name:"<>", q->name);
                                    continue;
                              }
                        
                              if(q->root == ql) q->root=ql->next; 
                              else qql->next=ql->next;
                                    
                              if (u && (u->sys_policy&SP_DENY_QUOTA)) {
                                    u->SetSysPolicy(SP_DENY_QUOTA, REMOVE, now);
                                    if(q->sys_policy_perm) u->sys_policy_perm=0;
                                    }
                              aFree(ql);
                              cli_error(cli, "unit %06X (%s) unbinded from quota %s",
                                    u->id, u->name?u->name:"<>", q->name);
                              continue;
                        }
                        qu=(qUlist*)aMalloc(sizeof(qUlist));
                        qu->u=u;
                        qu->next=q->root; 
                        q->root=qu;
                        qu->q_soft=qu->q_viol=0;
                        cli_error(cli, "unit %06X (%s) binded with quota %s",
                              u->id, u->name?u->name:"<>", q->name);
                  }
                  else
                        cli_error(cli, "unit %06X unknown, cannot bind", id);
            }           
      } else if (STREQ(param[0], "alert")) {
            User *x;
            u_short j;

            if (STRARG(param[1], "soft-reach")) {
                  if (STREQ(param[2], "user")) {
                        j=3;
                        user_soft_reach=1;
                  } else
                        j=2; 
                  
                  x=Users->getUser(param[j]);
                  if (!x) 
                        x=(User*)Users->getById(strtol(param[j], NULL, 16));
                  if(!x)
                        cli_error(cli, "user %s unknown", param[j]);
                  else 
                        soft_reach=x;
            }
            else if (STRARG(param[1], "hard-reach")) {
                  if (STREQ(param[2], "user")) {
                        j=3;
                        user_hard_reach=1;
                  } else
                        j=2; 
                  
                  x=Users->getUser(param[j]);
                  if (!x)
                        x=(User*)Users->getById(strtol(param[j], NULL, 16));
                  if (!x)
                        cli_error(cli, "user %s unknown", param[j]);
                  else if (x)
                        hard_reach=x;
            }
            else if (STRARG(param[1], "reset-back")) {
                  if (STREQ(param[2], "user")) {
                        j=3;
                        user_reset_back=1;
                  } else
                        j=2; 
                  
                  x=Users->getUser(param[j]);
                  if (!x)
                        x=(User*)Users->getById(strtol(param[j], NULL, 16));
                  if (!x)
                        cli_error(cli, "user %s unknown", param[j]);
                  else if (x)
                        reset_back=x;
            }
      } else if (STRARG(param[0], "lookup-delay")) {
            unsigned delay=strtol(param[1], NULL, 10);
            if(delay>1 && delay <24*60*60) {
                  delay=delay;
                  cli_error(cli, "quotas will be checked every %u seconds",delay);
            } 
            else
                  cli_error(cli, "lookup delay value invalid");
      }
      netams_rwlock_unlock(&rwlock);
      return CLI_OK;
}
//////////////////////////////////////////////////////////////////////////
void Service_Quotactl::ShowCfg(struct cli_def *cli, u_char flags){
      char buf[32];

      Qdef *q;

      netams_rwlock_rdlock(&rwlock);
      
      if(delay!=QUOTACTL_DELAY)
            cli_print(cli, "lookup-delay %d", delay);
      for (q=root; q!=NULL; q=q->next) {
            if (q->name) {
                  cli_bufprint(cli, "quota %s policy %s",
                        q->name,
                        (q->policy && q->policy->name)?q->policy->name:"<>");
                  if(q->sys_policy) GetSysPolicy(cli, q->sys_policy, q->sys_policy_perm);

                  if (q->h.in || q->h.out || q->h.softin || q->h.softout || q->h.sum || q->h.softsum) {
                        cli_bufprint(cli, " hour");
                        if (q->h.softin) cli_bufprint(cli, " %s soft-in", bytesQ2T(q->h.softin, buf));
                        if (q->h.softout) cli_bufprint(cli, " %s soft-out", bytesQ2T(q->h.softout, buf));
                        if (q->h.softsum) cli_bufprint(cli, " %s soft-sum", bytesQ2T(q->h.softsum, buf));
                        if (q->h.in) cli_bufprint(cli, " %s in", bytesQ2T(q->h.in, buf));
                        if (q->h.out) cli_bufprint(cli, " %s out", bytesQ2T(q->h.out, buf));
                        if (q->h.sum) cli_bufprint(cli, " %s sum", bytesQ2T(q->h.sum, buf));
                  }
             
                  if (q->d.in || q->d.out || q->d.softin || q->d.softout || q->d.sum || q->d.softsum) {
                        cli_bufprint(cli, " day");
                        if (q->d.softin) cli_bufprint(cli, " %s soft-in", bytesQ2T(q->d.softin, buf));
                        if (q->d.softout) cli_bufprint(cli, " %s soft-out", bytesQ2T(q->d.softout, buf));
                        if (q->d.softsum) cli_bufprint(cli, " %s soft-sum", bytesQ2T(q->d.softsum, buf));
                        if (q->d.in) cli_bufprint(cli, " %s in", bytesQ2T(q->d.in, buf));
                        if (q->d.out) cli_bufprint(cli, " %s out", bytesQ2T(q->d.out, buf));
                        if (q->d.sum) cli_bufprint(cli, " %s sum", bytesQ2T(q->d.sum, buf));
                  }

                  if (q->w.in || q->w.out || q->w.softin || q->w.softout || q->w.sum || q->w.softsum) {
                        cli_bufprint(cli, " week");
                        if (q->w.softin) cli_bufprint(cli, " %s soft-in", bytesQ2T(q->w.softin, buf));
                        if (q->w.softout) cli_bufprint(cli, " %s soft-out", bytesQ2T(q->w.softout, buf));
                        if (q->w.softsum) cli_bufprint(cli, " %s soft-sum", bytesQ2T(q->w.softsum, buf));
                        if (q->w.in) cli_bufprint(cli, " %s in", bytesQ2T(q->w.in, buf));
                        if (q->w.out) cli_bufprint(cli, " %s out", bytesQ2T(q->w.out, buf));
                        if (q->w.sum) cli_bufprint(cli, " %s sum", bytesQ2T(q->w.sum, buf));
                  }

                  if (q->m.in || q->m.out || q->m.softin || q->m.softout || q->m.sum || q->m.softsum) {
                        cli_bufprint(cli, " month");
                        if (q->m.softin) cli_bufprint(cli, " %s soft-in", bytesQ2T(q->m.softin, buf));
                        if (q->m.softout) cli_bufprint(cli, " %s soft-out", bytesQ2T(q->m.softout, buf));
                        if (q->m.softsum) cli_bufprint(cli, " %s soft-sum", bytesQ2T(q->m.softsum, buf));
                        if (q->m.in) cli_bufprint(cli, " %s in", bytesQ2T(q->m.in, buf));
                        if (q->m.out) cli_bufprint(cli, " %s out", bytesQ2T(q->m.out, buf));
                        if (q->m.sum) cli_bufprint(cli, " %s sum", bytesQ2T(q->m.sum, buf));
                  }
                  cli_bufprint(cli, "\n");
                  
                  if (q->root) {
                        cli_bufprint(cli, "bind quota %s to", q->name);
                        qUlist *p=NULL;
                        for (qUlist *ql=q->root;ql!=NULL;ql=ql->next) {
                              if (ql->u)
                                    cli_bufprint(cli, " %06X", ql->u->id);
                              else {
                                    if(q->root == ql) q->root=ql->next; 
                                    else p->next=ql->next;
                              }
                              p=ql;
                        }
                        cli_bufprint(cli, "\n");
                  }
            }
      }

      if (user_soft_reach || soft_reach) {
            cli_bufprint(cli, "alert soft-reach");
            if (user_soft_reach) cli_bufprint(cli, " <user>");
            if (soft_reach) {
                  if (soft_reach->name)
                        cli_bufprint(cli, " %s", soft_reach->name);
                  else
                        cli_bufprint(cli, " %06X", soft_reach->id);
            }
            cli_bufprint(cli, "\n");
      }

      if (user_hard_reach || hard_reach) {
            cli_bufprint(cli, "alert hard-reach");
            if (user_hard_reach) cli_bufprint(cli, " <user>");
            if (hard_reach) {
                  if (hard_reach->name)
                        cli_bufprint(cli, " %s", hard_reach->name);
                  else
                        cli_bufprint(cli, " %06X", hard_reach->id);
            }
            cli_bufprint(cli, "\n");
      }

      if (user_reset_back || reset_back) {
            cli_bufprint(cli, "alert reset-back");
            if (user_reset_back) cli_bufprint(cli, " <user>");
            if (reset_back) {
                  if (reset_back->name)
                        cli_bufprint(cli, " %s", reset_back->name);
                  else
                        cli_bufprint(cli, " %06X", reset_back->id);
            }
            cli_bufprint(cli, "\n");
      }
      netams_rwlock_unlock(&rwlock);
}
//////////////////////////////////////////////////////////////////////////
int cShowQuotactl(struct cli_def *cli, const char *cmd, char **argv, int argc){
      char buf[32], buf2[32];
      Qdef *q;
      NetUnit *u;
      policy_data *pd;
      Service *s=NULL;
      char *r_qname=NULL; oid r_id=0;

      for(u_char i=2;i<argc;) {
            if (STRARG(argv[i], "name")) {
                  r_qname=argv[i+1];
                  i+=2;
            } 
            else if (STRARG(argv[i], "unit")) {
                  if((u=Units->getUnit(argv[i+1]))) r_id=u->id;
                  else r_id=strtol(argv[i+1], NULL, 16);
                  i+=2;
            } else i++;
      }
        
      while((s=Services->getServiceNextByType(SERVICE_QUOTACTL,s))) {
            Service_Quotactl *cfg=(Service_Quotactl*)s;
            cli_print(cli, "service quotactl %u",cfg->instance);
            
            netams_rwlock_rdlock(&cfg->rwlock);
            
            for (q=cfg->root; q!=NULL; q=q->next) 
            if (!q->name) continue; 
            if (STREQ(q->name, r_qname)) {
                  cli_bufprint(cli, "QUOTA: %s\tpolicy %s\tset",
                        q->name, (q->policy && q->policy->name)?q->policy->name:"<>");
                  GetSysPolicy(cli, q->sys_policy,q->sys_policy_perm); 
                  cli_bufprint(cli, "\n");
                  
                  for (qUlist *ql=q->root;ql!=NULL;ql=ql->next) { 
                        if (!ql->u) continue;
                        
                        if (r_id==0 || (r_id!=0 && r_id==ql->u->id) ) {
                              u=ql->u;
                              if(!u->ap) continue;

                              pd=u->ap->Get(q->policy);
                              if(!pd) continue;
                              cli_bufprint(cli, " UNIT %06X\t(%s)\tSYST:",
                                    u->id, u->name?u->name:"<>");
                              GetSysPolicy(cli, u->sys_policy, u->sys_policy_perm);
                              cli_bufprint(cli, "\t");
                              
                              netams_rwlock_rdlock(&u->ap->rwlock);                             

                              if (q->h.softin)
                                    cli_print(cli, "  HOUR   in: %s, softquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->h.in, buf), bytesQ2T(q->h.softin, buf2),
                                          100.0*(double)pd->h.in/q->h.softin, pd->h.in>=q->h.softin?'-':'+');
                              if (q->h.in)
                                    cli_print(cli, "  HOUR   in: %s, hardquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->h.in, buf),
                                          bytesQ2T(q->h.in, buf2),
                                          100.0*(double)pd->h.in/q->h.in, pd->h.in>=q->h.in?'-':'+');
                              if (q->h.softout)
                                    cli_print(cli, "  HOUR  out: %s, softquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->h.out, buf),
                                          bytesQ2T(q->h.softout, buf2),
                                          100.0*(double)pd->h.out/q->h.softout,
                                          pd->h.out>=q->h.softout?'-':'+');
                              if (q->h.out)
                                    cli_print(cli, "  HOUR  out: %s, hardquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->h.out, buf),
                                          bytesQ2T(q->h.out, buf2),
                                          100.0*(double)pd->h.out/q->h.out,
                                          pd->h.out>=q->h.out?'-':'+');
                              if (q->h.softsum)
                                    cli_print(cli, "  HOUR  sum: %s, softquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->h.in+pd->h.out, buf),
                                          bytesQ2T(q->h.softsum, buf2),
                                          100.0*(double)(pd->h.in+pd->h.out)/q->h.softsum,
                                          (pd->h.in+pd->h.out)>=q->h.softsum?'-':'+');
                              if (q->h.sum)
                                    cli_print(cli, "  HOUR  sum: %s, hardquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->h.in+pd->h.out, buf),
                                          bytesQ2T(q->h.sum, buf2),
                                          100.0*(double)(pd->h.in+pd->h.out)/q->h.sum,
                                          (pd->h.in+pd->h.out)>=q->h.sum?'-':'+');

                              if (q->d.softin)
                                    cli_print(cli, "  DAY    in: %s, softquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->d.in, buf),
                                          bytesQ2T(q->d.softin, buf2),
                                          100.0*(double)pd->d.in/q->d.softin,
                                          pd->d.in>=q->d.softin?'-':'+');
                              if (q->d.in)
                                    cli_print(cli, "  DAY    in: %s, hardquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->d.in, buf),
                                          bytesQ2T(q->d.in, buf2),
                                          100.0*(double)pd->d.in/q->d.in,
                                          pd->d.in>=q->d.in?'-':'+');
                              if (q->d.softout)
                                    cli_print(cli, "  DAY   out: %s, softquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->d.out, buf),
                                          bytesQ2T(q->d.softout, buf2),
                                          100.0*(double)pd->d.out/q->d.softout,
                                          pd->d.out>=q->d.softout?'-':'+');
                              if (q->d.out)
                                    cli_print(cli, "  DAY   out: %s, hardquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->d.out, buf),
                                          bytesQ2T(q->d.out, buf2),
                                          100.0*(double)pd->d.out/q->d.out,
                                          pd->d.out>=q->d.out?'-':'+');
                              if (q->d.softsum)
                                    cli_print(cli, "  DAY   sum: %s, softquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->d.in+pd->d.out, buf),
                                          bytesQ2T(q->d.softsum, buf2),
                                          100.0*(double)(pd->d.in+pd->d.out)/q->d.softsum,
                                          (pd->d.in+pd->d.out)>=q->d.softsum?'-':'+');
                              if (q->d.sum)
                                    cli_print(cli, "  DAY   sum: %s, hardquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->d.in+pd->d.out, buf),
                                          bytesQ2T(q->d.sum, buf2),
                                          100.0*(double)(pd->d.in+pd->d.out)/q->d.sum,
                                          (pd->d.in+pd->d.out)>=q->d.sum?'-':'+');

                              if (q->w.softin)
                                    cli_print(cli, "  WEEK   in: %s, softquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->w.in, buf),
                                          bytesQ2T(q->w.softin, buf2),
                                          100.0*(double)pd->w.in/q->w.softin,
                                          pd->w.in>=q->w.softin?'-':'+');
                              if (q->w.in)
                                    cli_print(cli, "  WEEK   in: %s, hardquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->w.in, buf),
                                          bytesQ2T(q->w.in, buf2),
                                          100.0*(double)pd->w.in/q->w.in,
                                          pd->w.in>=q->w.in?'-':'+');
                              if (q->w.softout)
                                    cli_print(cli, "  WEEK  out: %s, softquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->w.out, buf),
                                          bytesQ2T(q->w.softout, buf2),
                                          100.0*(double)pd->w.out/q->w.softout,
                                          pd->w.out>=q->w.softout?'-':'+');
                              if (q->w.out)
                                    cli_print(cli, "  WEEK  out: %s, hardquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->w.out, buf),
                                          bytesQ2T(q->w.out, buf2),
                                          100.0*(double)pd->w.out/q->w.out,
                                          pd->w.out>=q->w.out?'-':'+');
                              if (q->w.softsum)
                                    cli_print(cli, "  WEEK  sum: %s, softquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->w.in+pd->w.out, buf),
                                          bytesQ2T(q->w.softsum, buf2),
                                          100.0*(double)(pd->w.in+pd->w.out)/q->w.softsum,
                                          (pd->w.in+pd->w.out)>=q->w.softsum?'-':'+');
                              if (q->w.sum)
                                    cli_print(cli, "  WEEK  sum: %s, hardquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->w.in+pd->w.out, buf),
                                          bytesQ2T(q->w.sum, buf2),
                                          100.0*(double)(pd->w.in+pd->w.out)/q->w.sum,
                                          (pd->w.in+pd->w.out)>=q->w.sum?'-':'+');

                              if (q->m.softin)
                                    cli_print(cli, "  MONTH  in: %s, softquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->m.in, buf),
                                          bytesQ2T(q->m.softin, buf2),
                                          100.0*(double)pd->m.in/q->m.softin,
                                          pd->m.in>=q->m.softin?'-':'+');
                              if (q->m.in)
                                    cli_print(cli, "  MONTH  in: %s, hardquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->m.in, buf),
                                          bytesQ2T(q->m.in, buf2),
                                          100.0*(double)pd->m.in/q->m.in,
                                          pd->m.in>=q->m.in?'-':'+');
                              if (q->m.softout)
                                    cli_print(cli, "  MONTH out: %s, softquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->m.out, buf),
                                          bytesQ2T(q->m.softout, buf2),
                                          100.0*(double)pd->m.out/q->m.softout,
                                          pd->m.out>=q->m.softout?'-':'+');
                              if (q->m.out)
                                    cli_print(cli, "  MONTH out: %s, hardquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->m.out, buf),
                                          bytesQ2T(q->m.out, buf2),
                                          100.0*(double)pd->m.out/q->m.out,
                                          pd->m.out>=q->m.out?'-':'+');
                              if (q->m.softsum)
                                    cli_print(cli, "  MONTH sum: %s, softquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->m.in+pd->m.out, buf),
                                          bytesQ2T(q->m.softsum, buf2),
                                          100.0*(double)(pd->m.in+pd->m.out)/q->m.softsum,
                                          (pd->m.in+pd->m.out)>=q->m.softsum?'-':'+');
                              if (q->m.sum)
                                    cli_print(cli, "  MONTH sum: %s, hardquota %s ratio %.2f%% -> [%c]",
                                          bytesQ2T(pd->m.in+pd->m.out, buf),
                                          bytesQ2T(q->m.sum, buf2),
                                          100.0*(double)(pd->m.in+pd->m.out)/q->m.sum,
                                          (pd->m.in+pd->m.out)>=q->m.sum?'-':'+');
                                    
                              netams_rwlock_unlock(&u->ap->rwlock);
                        }
                  }
            }
            netams_rwlock_unlock(&cfg->rwlock);
      }
      return CLI_OK;
}

//////////////////////////////////////////////////////////////////////////
void Service_Quotactl::Worker(){
      Qdef *q;
      NetUnit *u;
      policy_data *pd;
      u_short q_viol, q_soft;
      time_t now;

      aLog(D_DEBUG, "service quotactl:%u checking every %d seconds\n", instance, delay);
      while (1) {
            now=time(NULL);
            netams_rwlock_wrlock(&rwlock);
      
            for (q=root; q!=NULL; q=q->next)
            if (q->name) {
                  qUlist *p=NULL;
                  for (qUlist *ql=q->root;ql!=NULL;ql=ql->next) { 
                        if (ql->u) {
                              q_viol=q_soft=0;
                              u=ql->u;
                              if (!u->ap) goto NEXT;
                              
                              pd=u->ap->Get(q->policy);
                              if (!pd) goto NEXT;
                              
                              netams_rwlock_rdlock(&u->ap->rwlock);
                              
                              if (q->h.in) if (pd->h.in>=q->h.in) q_viol=1;
                              if (q->h.out) if (pd->h.out>=q->h.out) q_viol=1;
                              if (q->h.sum) if ((pd->h.in+pd->h.out)>=q->h.sum) q_viol=1;
                              if (q->h.softin) if (pd->h.in>=q->h.softin) q_soft=1;
                              if (q->h.softout) if (pd->h.out>=q->h.softout) q_soft=1;
                              if (q->h.softsum) if ((pd->h.in+pd->h.out)>=q->h.softsum) q_soft=1;

                              if (q->d.in) if (pd->d.in>=q->d.in) q_viol=1;
                              if (q->d.out) if (pd->d.out>=q->d.out) q_viol=1;
                              if (q->d.sum) if ((pd->d.in+pd->d.out)>=q->d.sum) q_viol=1;
                              if (q->d.softin) if (pd->d.in>=q->d.softin) q_soft=1;
                              if (q->d.softout) if (pd->d.out>=q->d.softout) q_soft=1;
                              if (q->d.softsum) if ((pd->d.in+pd->d.out)>=q->d.softsum) q_soft=1;
                              
                              if (q->w.in) if (pd->w.in>=q->w.in) q_viol=1;
                              if (q->w.out) if (pd->w.out>=q->w.out) q_viol=1;
                              if (q->w.sum) if ((pd->w.in+pd->w.out)>=q->w.sum) q_viol=1;
                              if (q->w.softin) if (pd->w.in>=q->w.softin) q_soft=1;
                              if (q->w.softout) if (pd->w.out>=q->w.softout) q_soft=1;
                              if (q->w.softsum) if ((pd->w.in+pd->w.out)>=q->w.softsum) q_soft=1;
                              
                              if (q->m.in) if (pd->m.in>=q->m.in) q_viol=1;
                              if (q->m.out) if (pd->m.out>=q->m.out) q_viol=1;
                              if (q->m.sum) if ((pd->m.in+pd->m.out)>=q->m.sum) q_viol=1;
                              if (q->m.softin) if (pd->m.in>=q->m.softin) q_soft=1;
                              if (q->m.softout) if (pd->m.out>=q->m.softout) q_soft=1;
                              if (q->m.softsum) if ((pd->m.in+pd->m.out)>=q->m.softsum) q_soft=1;
                              
                              netams_rwlock_unlock(&u->ap->rwlock);                       

                              if (!q_viol && (u->sys_policy&q->sys_policy)) {
                                    u->SetSysPolicy(q->sys_policy, REMOVE, now);
                                    u->sys_policy_perm=0;
                                    aLog(D_WARN, "unit %06X (%s) quota %s reset back\n", u->id, u->name?u->name:"<>", q->name);
                                    SendAlert(u, q, 0);
                                    ql->q_soft=ql->q_viol=0;
                                    cAccessScriptCall(PASS, u, "QUOTA RESET");
                              }
                              if (q_viol && !(u->sys_policy&q->sys_policy)) {
                                    u->SetSysPolicy(q->sys_policy, ADD, now);
                                    u->sys_policy_perm=q->sys_policy_perm;
                                    aLog(D_WARN, "unit %06X (%s) violated quota %s\n", u->id, u->name?u->name:"<>", q->name);
                                    SendAlert(u, q, 1);
                                    ql->q_viol=q_viol;
                                    cAccessScriptCall(DROP, u, "QUOTA VIOLATE");
                              }
                              if (q_soft && !(u->sys_policy&q->sys_policy) && !ql->q_soft) {
                                    aLog(D_WARN, "unit %06X (%s) reached soft quota %s\n", u->id, u->name?u->name:"<>", q->name);
                                    SendAlert(u, q, 2);
                                    ql->q_soft=q_soft;
                              }
                              if (!q_soft && ql->q_soft) {
                                    aLog(D_WARN, "unit %06X (%s) soft quota %s reset back\n", u->id, u->name?u->name:"<>", q->name);
                                    ql->q_soft=0;
                              }
                        } else {
                                    if(q->root == ql) q->root=ql->next; 
                              else p->next=ql->next;
                        }
NEXT:                   
                        p=ql;
                  }
            }
            netams_rwlock_unlock(&rwlock);
            
            Sleep(delay); // quotas will be checked every cfg->delay seconds
      }
}
//////////////////////////////////////////////////////////////////////////
void Service_Quotactl::Cancel(){
      time_t now=time(NULL);

      netams_rwlock_wrlock(&rwlock);
      netams_rwlock_rdlock(&Units->rwlock);

      for (Qdef *q=root; q!=NULL;) {
            for(qUlist *ql=q->root;ql!=NULL;) {
                  NetUnit *u=ql->u;
                        if (u && (u->sys_policy&q->sys_policy)) {
                        u->SetSysPolicy(q->sys_policy, REMOVE, now);    
                                if(q->sys_policy_perm) u->sys_policy_perm=0;
                  }
                  qUlist *ptr=ql;
                  ptr=ql;
                  ql=ql->next;
            }
            q=q->next;
      }
      netams_rwlock_unlock(&Units->rwlock);
      netams_rwlock_unlock(&rwlock);
}
//////////////////////////////////////////////////////////////////////////
void Service_Quotactl::SendAlert(NetUnit *u, Qdef *q, u_char dir){       // dir=1:violates; =0:back; =2:soft_quota_reached
      if(!u->email) return; //nowhere to send
      Service* alerter=Services->getServiceNextByType(SERVICE_ALERTER,NULL);
      if (!alerter) return;

      Message *msg;
      alert *al;

      msg = MsgMgr->New(MSG_ALERT);
      
      al=((Message_Alert*)msg)->al;
      al->sent=time(NULL);
      al->expired=al->sent+60*60; // one hour expire
      al->report_id=0x06101; 
      al->tries=0; 
      
      char *subject, *message, *buf, buffer[255];
      subject=message=NULL; 

      timeU2T(time(NULL), buffer);

      print_to_string(&message, "This is automatically generated report by %s\nTime: %s\n\n", 
            SHOW_VERSION, buffer);
      
      //we do not need lock here because we locked it in sQuotactl already
      switch (dir) {    
            case 0:
                  if (reset_back) al->user_id[0]=reset_back->id; else al->user_id[0]=0;
                  if (user_reset_back)  al->unit_id[0]=u->id; 
                  print_to_string(&subject, "Quotactl: unit %s quota RETURN", u->name?u->name:"<>", q->name);
                  print_to_string(&message, "NeTAMS Quotactl service have detected quota RETURN for unit %s (%06X), quota %s\n", u->name?u->name:"<>", u->id, q->name);
                  break;
            case 1:
                  if (hard_reach) al->user_id[0]=hard_reach->id; else al->user_id[0]=0;
                  if (user_hard_reach)  al->unit_id[0]=u->id; 
                  print_to_string(&subject, "Quotactl: unit %s quota VIOLATION", u->name?u->name:"<>", q->name);
                  print_to_string(&message, "NeTAMS Quotactl service have detected quota HARD REACH for unit %s (%06X), quota %s\n", u->name?u->name:"<>", u->id, q->name);
                  break;
            case 2:
                  if (soft_reach) al->user_id[0]=soft_reach->id; else al->user_id[0]=0;
                  if (user_soft_reach)  al->unit_id[0]=u->id; 
                  print_to_string(&subject, "Quotactl: unit %s quota SOFT REACH", u->name?u->name:"<>", q->name);
                  print_to_string(&message, "NeTAMS Quotactl service have detected quota SOFT REACH for unit %s (%06X), quota %s\n", u->name?u->name:"<>", u->id, q->name);
                  break;
      }     

      print_to_string(&message, "\n################################");
      print_to_string(&message, "\nCurrent quotactl status follows:\n\n");
      snprintf(buffer, 254, "show quota name %s oid %06X", q->name, u->id);
      buf = cExec(buffer);
      print_to_string(&message, "%s", buf);
      aFree(buf);

      print_to_string(&message, "\n####################################");
      print_to_string(&message, "\nCurrent user traffic status follows:\n\n");
      snprintf(buffer, 245, "show list full oid %06X", u->id);
      buf = cExec(buffer);
      print_to_string(&message, "%s", buf);
      aFree(buf);

      al->data=NULL;
      print_to_string(&al->data, "%s\n%s\n", subject, message);
      aFree(subject);   aFree(message);

      aDebug(DEBUG_ALERT, "alert (quota) %u complete, data is %d bytes\n", al->alert_id, strlen(al->data));
      alerter->ProcessMessage(msg);
}
//////////////////////////////////////////////////////////////////////////
void sQuotactlGetValue(u_char *i, char *param[], qstat *q){
      u_short j=*i+1;
      unsigned long long data;
      while (1) {
            data=bytesT2Q(param[j]);

            if (STREQ(param[j+1], "in")) q->in=data;
            else if (STREQ(param[j+1], "out")) q->out=data;
            else if (STREQ(param[j+1], "sum")) q->sum=data;
            else if (STREQ(param[j+1], "soft-in")) q->softin=data;
            else if (STREQ(param[j+1], "soft-out")) q->softout=data;
            else if (STREQ(param[j+1], "soft-sum")) q->softsum=data;
            else break;

            j+=2;
            }
      *i=j-2;
}
//////////////////////////////////////////////////////////////////////////

Generated by  Doxygen 1.6.0   Back to index