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

s_quota.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_quota.c,v 1.129 2009-08-01 09:23:55 anton Exp $ */

#include "netams.h"

Service *Quota=NULL;
static int initialized=0;

//////////////////////////////////////////////////////////////////////////////////////////
int cShowQuota          (struct cli_def *cli, const char *cmd, char **argv, int argc);
int cQuotaSet           (struct cli_def *cli, const char *cmd, char **argv, int argc);
int cQuotaNotify  (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, "quota",     PRIVILEGE_UNPRIVILEGED, MODE_EXEC, cShowQuota,        "quota status" },
{ 0, 0, 0, "policy",    PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cServiceProcessCfg,           NULL },
{ 0, 0, 0, "block-policy", PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cServiceProcessCfg,  NULL },
{ 0, 0, 0, "soft-treshold", PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cServiceProcessCfg, NULL },
{ 22, 0, 0, "notify",   PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, NULL,                         NULL },
{ 23, 22, 0, "soft",    PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cQuotaNotify,                 NULL },
{ 0, 23, 0, "owner",    PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cQuotaNotify,                 NULL },
{ 0, 23, 0, "none",     PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cQuotaNotify,                 NULL },
{ 24, 22, 0, "hard",    PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cQuotaNotify,                 NULL },
{ 0, 24, 0, "owner",    PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cQuotaNotify,                 NULL },
{ 0, 24, 0, "none",     PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cQuotaNotify,                 NULL },
{ 25, 22, 0, "return",  PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cQuotaNotify,                 NULL },
{ 0, 25, 0, "owner",    PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cQuotaNotify,                 NULL },
{ 0, 25, 0, "none",           PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cQuotaNotify,                 NULL },
{ 0, 0, 0, "set",       PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cQuotaSet,                    NULL },
{ 0, 0, 0, "start",     PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cServiceStart,          NULL },
{ 0, 0, 0, "stop",      PRIVILEGE_UNPRIVILEGED, MODE_QUOTA, cServiceStop,           NULL },
{ -1, 0, 0, NULL,  0, 0, NULL, NULL }
};
//////////////////////////////////////////////////////////////////////////////////////////
void sQuSendAlert(NetUnit *u, sQuotaData *q, u_char dir);
void sQuotaGetValue(u_char *i, char *param[], qstat *q);
void FillQuotaData(void *res, void *row, char* (*getRowData)(void*, void* , u_char));
//////////////////////////////////////////////////////////////////////////////////////////
class Service_Quota: public Service {
      public:
            Policy *default_policy;
            Policy *default_fw_block_policy; //this policy will be added to all units fw list when blocked
            policy_flag default_fw_block_policy_flags;

            u_char default_soft_treshold;
            Service *st;
            char *filename;

            pthread_rwlock_t rwlock; // for multiple threads access same config data

            oid notify_soft[S_QUOTA_DEF_arraysize];
            oid notify_hard[S_QUOTA_DEF_arraysize];
            oid notify_return[S_QUOTA_DEF_arraysize];

            Service_Quota();
            ~Service_Quota();

            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 ProcessData();
            void RestoreQuota();
            void QuotaAction(NetUnit *u, sQuotaData *q, u_char action, time_t now);
};

Service* InitQuotaService() {
      Service *s;
      if(!initialized) {
            InitCliCommands(cmd_db);
            initialized = 1;
      }
      s = (Service*)new Service_Quota();
      s->serv_flags|=SERVICE_FLAG_SINGLE;
      return s;
}
//////////////////////////////////////////////////////////////////////////////////////////
Service_Quota::Service_Quota():Service(SERVICE_QUOTA) {
      default_soft_treshold=S_QUOTA_DEF_soft_treshold;
      default_policy=NULL;
      default_fw_block_policy=NULL;
      default_fw_block_policy_flags=POLICY_FLAG_NONE;
      st=NULL;
      filename=NULL;
      print_to_string(&filename, "quota.%u", instance);

      notify_soft[0]=S_QUOTA_DEF_notify_soft;
      notify_hard[0]=S_QUOTA_DEF_notify_hard;
      notify_return[0]=S_QUOTA_DEF_notify_return;
      for (u_char i=1; i<S_QUOTA_DEF_arraysize; i++) {
            notify_soft[i]=0;
            notify_hard[i]=0;
            notify_return[i]=0;
      }
    netams_rwlock_init(&rwlock, NULL);
      Quota=this;
}
Service_Quota::~Service_Quota() {
    Quota=NULL;
    netams_rwlock_destroy(&rwlock);
    aFree(filename);
}
//////////////////////////////////////////////////////////////////////////////////////////
int Service_Quota::ProcessCfg(struct cli_def *cli, char **param, int argc, u_char no_flag){

      netams_rwlock_wrlock(&rwlock);

      if (STRARG(param[0], "policy")) {
            Policy *p;
            if ((p=PolicyL->getPolicy(param[1]))) {
                  cli_error(cli, "default policy is set to %s", param[1]);
                  default_policy=p;
            } else
                  cli_error(cli, "no such policy exist: %s", param[1]);
      }
      else if (STRARG(param[0], "block-policy")) {
            Policy *p;
            policy_flag flags=POLICY_FLAG_NONE;
            char *c_param=param[1];

            if (c_param[0]=='!') { flags|=POLICY_FLAG_INV; c_param++; }
            if (c_param[0]=='%') { flags|=POLICY_FLAG_BRK; c_param++; }
            if (c_param[0]=='!') { flags|=POLICY_FLAG_INV; c_param++; }

            if ((p=PolicyL->getPolicy(c_param))) {
                  default_fw_block_policy=p;
                  default_fw_block_policy_flags=flags;
                  cli_error(cli, "block policy set to %s%s%s",
                        (flags&POLICY_FLAG_INV)?"!":"",
                        (flags&POLICY_FLAG_BRK)?"%":"", c_param);
            } else
                  cli_error(cli, "no such policy exist: %s", param[1]);
      }
      else if (STRARG(param[0], "soft-treshold")) {
            u_char st=strtol(param[1], NULL, 10);
            if (st>100) {
                  cli_error(cli, "invalid soft treshold value: %u (must be between 0 and 100)", st);
            }
            else {
                  cli_error(cli, "soft treshold set to %u", st);
                  default_soft_treshold=st;
            }
      }
      netams_rwlock_unlock(&rwlock);
      return CLI_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////
void Service_Quota::ShowCfg(struct cli_def *cli, u_char flags){
        netams_rwlock_rdlock(&rwlock);

      if (default_soft_treshold!=S_QUOTA_DEF_soft_treshold)
            cli_print(cli, "soft-treshold %d", default_soft_treshold);
      if (default_policy) cli_print(cli, "policy %s", default_policy->name);
      if (default_fw_block_policy)
            cli_print(cli, "block-policy %s%s%s",
                  (default_fw_block_policy_flags&POLICY_FLAG_INV)?"!":"",
                  (default_fw_block_policy_flags&POLICY_FLAG_BRK)?"%":"",
                  default_fw_block_policy->name);

      // default notify on soft quotas
      u_char j=0; for (u_char i=0; i<S_QUOTA_DEF_arraysize; i++) if (notify_soft[i]) j++;
      if (j) {
            cli_bufprint(cli, "notify soft");
            if (notify_soft[0]) cli_bufprint(cli, " owner");
            for (u_char i=1; i<S_QUOTA_DEF_arraysize; i++)
                  if (notify_soft[i]) cli_bufprint(cli, " %06X", notify_soft[i]);
            cli_bufprint(cli, "\n");
      }

      // default notify on hard quotas
      j=0; for (u_char i=0; i<S_QUOTA_DEF_arraysize; i++) if (notify_hard[i]) j++;
      if (j) {
            cli_bufprint(cli, "notify hard");
            if (notify_hard[0]) cli_bufprint(cli, " owner");
            for (u_char i=1; i<S_QUOTA_DEF_arraysize; i++)
                  if (notify_hard[i]) cli_bufprint(cli, " %06X", notify_hard[i]);
            cli_bufprint(cli, "\n");
      }

      // default notify on quotas return
      j=0; for (u_char i=0; i<S_QUOTA_DEF_arraysize; i++) if (notify_return[i]) j++;
      if (j) {
            cli_bufprint(cli, "notify return");
            if (notify_return[0]) cli_bufprint(cli, " owner");
            for (u_char i=1; i<S_QUOTA_DEF_arraysize; i++)
                  if (notify_return[i]) cli_bufprint(cli, " %06X", notify_return[i]);
            cli_bufprint(cli, "\n");
      }
      netams_rwlock_unlock(&rwlock);
}
//////////////////////////////////////////////////////////////////////////////////////////
void Service_Quota::Worker(){
//    time_t now;

      st = aStorageGetAccepted(ST_CONN_QUOTA);
      if (st==NULL) {
            aLog(D_WARN, "quota service requires at least one storage to be up, skipping quotas\n");
            return;
    }

      ((Service_Storage_Interface*)st)->SaveFile(filename,ST_CONN_QUOTA);

      while(!((Service_Storage_Interface*)st)->stLoad(ST_CONN_QUOTA, &FillQuotaData)) {
                aLog(D_WARN, "Service quota can't obtain data from storage:%u\n",st->instance);
                Sleep(10);
    }

      RestoreQuota(); //restore Quota state

      aLog(D_DEBUG, "service quota:%u checking every processor delay: %d seconds\n", instance, Processor->delay);

      while (1) {
            Sleep(0);
            aDebug(DEBUG_QUOTA, "Checking quotas (every %d seconds)\n", Processor->delay);
            ProcessData();
      }
}

//////////////////////////////////////////////////////////////////////////////////////////
void Service_Quota::QuotaAction(NetUnit *u, sQuotaData *q, u_char action, time_t now) {

      if(action==ADD) {
            if(q->fw_block_policy) {
                  if(u->fp==NULL) u->fp=new PdList();
                  u->fp->Add(q->fw_block_policy, q->fw_block_policy_flags, 0);
            }
            else if(default_fw_block_policy) {
                  if(u->fp==NULL) u->fp=new PdList();
                  u->fp->Add(default_fw_block_policy, default_fw_block_policy_flags, 0);
            } else
                  u->SetSysPolicy(SP_DENY_QUOTA, ADD, now);

            cAccessScriptCall(DROP, u, "QUOTA VIOLATE");

            aLog(D_WARN, "unit %06X (%s) violated quota\n", u->id, u->name?u->name:"<>");
            LogEvent( QUOTA, u->id, 0, 0, "unit %06X (%s) violated quota", u->id, u->name?u->name:"<>");
      } else {
            if(q->fw_block_policy && u->fp) {
                  if (!u->fp->Delete(q->fw_block_policy)) delete u->fp; u->fp=NULL;
            }
            else if(default_fw_block_policy && u->fp) {
                  if (!u->fp->Delete(default_fw_block_policy)) delete u->fp; u->fp=NULL;
            }
            u->SetSysPolicy(SP_DENY_QUOTA, REMOVE, now);

            cAccessScriptCall(PASS, u, "QUOTA RESET");
            aLog(D_WARN, "unit %06X (%s) quota reset back\n", u->id, u->name?u->name:"<>");
            LogEvent( QUOTA, u->id, 0, 0, "unit %06X (%s) quota reset back", u->id, u->name?u->name:"<>");
      }
}
//////////////////////////////////////////////////////////////////////////////////////////
void Service_Quota::RestoreQuota() {
      sQuotaData *q;
      NetUnit *u;
      time_t now = time(NULL);

      aLog(D_INFO, "Restoring units quota\n");

      netams_rwlock_rdlock(&Units->rwlock);
      for (u=(NetUnit*)Units->root; u!=NULL; u=(NetUnit*)u->next) {
            for(q=u->quotadata; q!=NULL; q=q->next) {
                  if(q->flags&QUOTA_BLOCKED)
                        QuotaAction(u, q, ADD, now);
                  q->flags&=~QUOTA_UPDATE;
                  aDebug(DEBUG_QUOTA, "Unit: %06X soft %u act %u blo %u softblo %u\n",
                        u->id, q->soft_treshold,
                        (q->flags&QUOTA_ACTIVE),
                        (q->flags&QUOTA_BLOCKED),
                        (q->flags&QUOTA_SOFTBLOCKED));
            }
      }
      netams_rwlock_unlock(&Units->rwlock);
}
//////////////////////////////////////////////////////////////////////////////////////////
void Service_Quota::ProcessData() {
      FILE *file=NULL;
      NetUnit *u;
      sQuotaData *q;
      policy_data *pd;
      u_char q_viol, q_soft;
      time_t now=time(NULL);

      netams_rwlock_rdlock(&Units->rwlock);
      for (u=(NetUnit*)Units->root; u!=NULL; u=(NetUnit*)u->next) {
         for(q=u->quotadata;q!=NULL; q=q->next) {
            if((q->flags&QUOTA_ACTIVE) && u->ap && (pd=u->ap->Get(q->policy))) {
                  q_viol=q_soft=0;
                  netams_rwlock_rdlock(&u->ap->rwlock);

                  if (q->h.in && pd->h.in>=q->h.in) q_viol=1;
                  if (q->h.out && pd->h.out>=q->h.out) q_viol=1;
                  if (q->h.sum && (pd->h.in+pd->h.out)>=q->h.sum) q_viol=1;
                  if (q->h.in && q->soft_treshold && pd->h.in>=q->soft_treshold*q->h.in/100) q_soft=1;
                  if (q->h.out && q->soft_treshold && pd->h.out>=q->soft_treshold*q->h.out/100) q_soft=1;
                  if (q->h.sum && q->soft_treshold && (pd->h.in+pd->h.out)>=q->soft_treshold*q->h.sum/100) q_soft=1;

                  if (q->d.in && pd->d.in>=q->d.in) q_viol=1;
                  if (q->d.out && pd->d.out>=q->d.out) q_viol=1;
                  if (q->d.sum && (pd->d.in+pd->d.out)>=q->d.sum) q_viol=1;
                  if (q->d.in && q->soft_treshold && pd->d.in>=q->soft_treshold*q->d.in/100) q_soft=1;
                  if (q->d.out && q->soft_treshold && pd->d.out>=q->soft_treshold*q->d.out/100) q_soft=1;
                  if (q->d.sum && q->soft_treshold && (pd->d.in+pd->d.out)>=q->soft_treshold*q->d.sum/100) q_soft=1;

                  if (q->w.in && pd->w.in>=q->w.in) q_viol=1;
                  if (q->w.out && pd->w.out>=q->w.out) q_viol=1;
                  if (q->w.sum && (pd->w.in+pd->w.out)>=q->w.sum) q_viol=1;
                  if (q->w.in && q->soft_treshold && pd->w.in>=q->soft_treshold*q->w.in/100) q_soft=1;
                  if (q->w.out && q->soft_treshold && pd->w.out>=q->soft_treshold*q->w.out/100) q_soft=1;
                  if (q->w.sum && q->soft_treshold && (pd->w.in+pd->w.out)>=q->soft_treshold*q->w.sum/100) q_soft=1;

                  if (q->m.in && pd->m.in>=q->m.in) q_viol=1;
                  if (q->m.out && pd->m.out>=q->m.out) q_viol=1;
                  if (q->m.sum && (pd->m.in+pd->m.out)>=q->m.sum) q_viol=1;
                  if (q->m.in && q->soft_treshold && pd->m.in>=q->soft_treshold*q->m.in/100) q_soft=1;
                  if (q->m.out && q->soft_treshold && pd->m.out>=q->soft_treshold*q->m.out/100) q_soft=1;
                  if (q->m.sum && q->soft_treshold && (pd->m.in+pd->m.out)>=q->soft_treshold*q->m.sum/100) q_soft=1;

                  netams_rwlock_unlock(&u->ap->rwlock);
                  // deal with hard quotas...

                  if (!q_viol && (q->flags&QUOTA_BLOCKED)) { // viol=0, blocked=1 -> reset it back
                        QuotaAction(u, q, REMOVE, now);
                        q->flags&=~QUOTA_BLOCKED;
                        q->flags&=~QUOTA_SOFTBLOCKED;
                        sQuSendAlert(u, q, 0);
                        q->flags|=QUOTA_UPDATE;
                  }
                  else if (q_viol && !(q->flags&QUOTA_BLOCKED)) { // viol=1, blocked=0 -> block it
                        QuotaAction(u, q, ADD, now);
                        q->flags&=~QUOTA_SOFTBLOCKED;
                        q->flags|=QUOTA_BLOCKED;
                        q->blocked_time=now;
                        sQuSendAlert(u, q, 1);
                        q->flags|=QUOTA_UPDATE;
                  }
                  else if (!q_viol && !(q->flags&QUOTA_BLOCKED)) { // viol=0, blocked=0 -> pass
                  }
                  else  { // viol=1, blocked=1 -> do nothing
                  }

                  // deal with soft quotas...
                  // soft=1, blocked=0, viol=0 - notify
                  if (q_soft && !q_viol && !(q->flags&QUOTA_SOFTBLOCKED)) {
                        aLog(D_WARN, "unit %06X (%s) reached soft quota\n", u->id, u->name?u->name:"<>");
                        LogEvent( QUOTA, u->id, 0, 0, "unit %06X (%s) reached soft quota", u->id, u->name?u->name:"<>");
                        q->flags|=QUOTA_SOFTBLOCKED;
                        sQuSendAlert(u, q, 2);
                        q->flags|=QUOTA_UPDATE;
                  } else if(!q_soft && (q->flags&QUOTA_SOFTBLOCKED)) { // silently remove softblocked flag
                        q->flags&=~QUOTA_SOFTBLOCKED;
                        q->flags|=QUOTA_UPDATE;
                  }

            }

            if (q->flags&QUOTA_UPDATE) {
                  if(!file) {
                        file=fopen(filename,"a");
                        if(!file) {
                              aLog(D_ERR, "Can't create temporary file %s: %s\n", filename, strerror(errno));
                              netams_rwlock_unlock(&Units->rwlock);
                              return;
                        }
                        setlinebuf(file);
                  }
                  q->flags&=~QUOTA_UPDATE;
                  fprintf(file, "%u,%u,0,%u,%u,%lu,%u,%u,%u,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%u,%u\n",u->id, q->policy->id,/*syspolicy,*/q->soft_treshold,q->flags,q->blocked_time, q->nso, q->nho, q->nro,q->h.in,q->h.out,q->h.sum, q->d.in,q->d.out,q->d.sum, q->w.in,q->w.out,q->w.sum, q->m.in,q->m.out,q->m.sum, q->fw_block_policy?q->fw_block_policy->id:0, q->fw_block_policy_flags);
            }
         } // for all quotas
      } // for all units and in unit is quota-active
      netams_rwlock_unlock(&Units->rwlock);

      if(file) {
            fclose(file);
            ((Service_Storage_Interface*)st)->SaveFile(filename,ST_CONN_QUOTA);
      }
}

//////////////////////////////////////////////////////////////////////////////////////////
void Service_Quota::Cancel(){
      ProcessData();
      ((Service_Storage_Interface*)st)->Close(ST_CONN_QUOTA);
}

//////////////////////////////////////////////////////////////////////////////////////////
int cShowQuota(struct cli_def *cli, const char *cmd, char **argv, int argc){
      NetUnit *u, *ut=NULL;
      User *us=NULL;
      sQuotaData *q;
      policy_data *pd;
      unsigned total=0, enabled=0, active=0, blocked=0, softblocked=0, unit_spec=0;
      static char buf[32], buf2[32];
      u_char i=2;

      Service *s=Quota;
        if(!s) {
            cli_print(cli, "Service not enabled");
            return CLI_OK;
      }
//    Quota_cfg *cfg=(Quota_cfg*)s->cfg;

      if ((argv[i]) && (ut=aParseUnit(argv, &i)))
            unit_spec=1;
      else if (STREQ(argv[2], "list")) {
            cli_print(cli, "Units where quota is enabled:\n");
//          netams_rwlock_rdlock(&cfg->rwlock);
//          netams_rwlock_rdlock(&Units->rwlock);
            for (u=(NetUnit*)Units->root; u!=NULL; u=(NetUnit*)u->next)
                  if (u->quotadata) cli_print(cli, "%s %06X ", u->name?u->name:"<\?\?>", u->id);
//          netams_rwlock_unlock(&Units->rwlock);
//          netams_rwlock_unlock(&cfg->rwlock);
            return CLI_OK;
      }

//    int err1=netams_rwlock_tryrdlock(&cfg->rwlock);
//    if(err1==EBUSY) netams_rwlock_rdlock(&cfg->rwlock); // deadlock is here.
//    int err2=netams_rwlock_tryrdlock(&Units->rwlock);
//    if(err2==EBUSY) netams_rwlock_rdlock(&Units->rwlock);
      for (u=(NetUnit*)Units->root; u!=NULL; u=(NetUnit*)u->next){
         total++;
         for(q=u->quotadata;q!=NULL; q=q->next) {
            enabled++;
            if (q->flags&QUOTA_ACTIVE) active++;
            if (q->flags&QUOTA_BLOCKED) blocked++;
            if (q->flags&QUOTA_SOFTBLOCKED) softblocked++;
            if (ut && ut!=u) continue;  //unit specified

            cli_print(cli, "OID: %06X (%s) policy: %s", u->id, u->name?u->name:"<\?\?>", q->policy?q->policy->name:"");
            if (q->fw_block_policy && q->fw_block_policy->name)
                  cli_print(cli, "block-policy: %s%s%s",
                        (q->fw_block_policy_flags&POLICY_FLAG_INV)?"!":"",
                        (q->fw_block_policy_flags&POLICY_FLAG_BRK)?"%":"",
                        q->fw_block_policy->name);
            cli_print(cli, "soft-treshold: %d%% %s%s%s%s",
                  q->soft_treshold,
                  q->flags&QUOTA_ACTIVE?"ACTIVE ":"",
                  q->flags&QUOTA_SOFTBLOCKED?"SOFTBLOCKED ":"",
                  q->flags&QUOTA_BLOCKED?"BLOCKED ":"",
                  q->flags&QUOTA_UPDATE?"NEED_UPDATE ":"");
            cli_print(cli, "Notification: soft %s%s, hard %s%s, return %s%s",
                  q->flags&QUOTA_NSS?"owner ":"",
                  q->nso?((us=(User*)Users->getById(q->nso))?us->name:"\?\?"):"",
                  q->flags&QUOTA_NHS?"owner ":"",
                  q->nho?((us=(User*)Users->getById(q->nho))?us->name:"\?\?"):"",
                  q->flags&QUOTA_NRS?"owner ":"",
                  q->nro?((us=(User*)Users->getById(q->nro))?us->name:"\?\?"):"") ;

            if (u->ap && (pd=u->ap->Get(q->policy))) {
                  netams_rwlock_rdlock(&u->ap->rwlock);

                  if (q->h.in && q->soft_treshold)
                        cli_print(cli, "  HOUR   in: %s, softquota %s ratio %.0f%% -> [%c]",
                              bytesQ2T(pd->h.in, buf),
                              bytesQ2T(q->soft_treshold*q->h.in/100, buf2),
                              10000*(double)pd->h.in/(q->h.in*q->soft_treshold),
                              pd->h.in>=(double)q->soft_treshold/100*q->h.in?'-':'+');
                  if (q->h.in)
                        cli_print(cli, "  HOUR   in: %s, hardquota %s ratio %.0f%% -> [%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.out && q->soft_treshold)
                        cli_print(cli, "  HOUR  out: %s, softquota %s ratio %.0f%% -> [%c]",
                              bytesQ2T(pd->h.out, buf),
                              bytesQ2T(q->soft_treshold*q->h.out/100, buf2),
                              10000*(double)pd->h.out/(q->h.out*q->soft_treshold),
                              pd->h.out>=(double)q->soft_treshold/100*q->h.out?'-':'+');
                  if (q->h.out)
                        cli_print(cli, "  HOUR  out: %s, hardquota %s ratio %.0f%% -> [%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.sum && q->soft_treshold)
                        cli_print(cli, "  HOUR  sum: %s, softquota %s ratio %.0f%% -> [%c]",
                              bytesQ2T(pd->h.in+pd->h.out, buf),
                              bytesQ2T(q->soft_treshold*q->h.sum/100, buf2),
                              10000*(double)(pd->h.in+pd->h.out)/(q->h.sum*q->soft_treshold),
                              (pd->h.in+pd->h.out)>=(double)q->soft_treshold/100*q->h.sum?'-':'+');
                  if (q->h.sum)
                        cli_print(cli, "  HOUR  sum: %s, hardquota %s ratio %.0f%% -> [%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.in && q->soft_treshold)
                        cli_print(cli, "  DAY     in: %s, softquota %s ratio %.0f%% -> [%c]",
                              bytesQ2T(pd->d.in, buf),
                              bytesQ2T(q->soft_treshold*q->d.in/100, buf2),
                              10000*(double)pd->d.in/(q->d.in*q->soft_treshold),
                              pd->d.in>=(double)q->soft_treshold/100*q->d.in?'-':'+');
                  if (q->d.in)
                        cli_print(cli, "  DAY     in: %s, hardquota %s ratio %.0f%% -> [%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.out && q->soft_treshold)
                        cli_print(cli, "  DAY    out: %s, softquota %s ratio %.0f%% -> [%c]",
                              bytesQ2T(pd->d.out, buf),
                              bytesQ2T(q->soft_treshold*q->d.out/100, buf2),
                              10000*(double)pd->d.out/(q->d.out*q->soft_treshold),
                              pd->d.out>=(double)q->soft_treshold/100*q->d.out?'-':'+');
                  if (q->d.out)
                        cli_print(cli, "  DAY    out: %s, hardquota %s ratio %.0f%% -> [%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.sum && q->soft_treshold)
                        cli_print(cli, "  DAY    sum: %s, softquota %s ratio %.0f%% -> [%c]",
                              bytesQ2T(pd->d.in+pd->d.out, buf),
                              bytesQ2T(q->soft_treshold*q->d.sum/100, buf2),
                              10000*(double)(pd->d.in+pd->d.out)/(q->d.sum*q->soft_treshold),
                              (pd->d.in+pd->d.out)>=(double)q->soft_treshold/100*q->d.sum?'-':'+');
                  if (q->d.sum)
                        cli_print(cli, "  DAY    sum: %s, hardquota %s ratio %.0f%% -> [%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.in && q->soft_treshold)
                        cli_print(cli, "  WEEK   in: %s, softquota %s ratio %.0f%% -> [%c]",
                              bytesQ2T(pd->w.in, buf),
                              bytesQ2T(q->soft_treshold*q->w.in/100, buf2),
                              10000*(double)pd->w.in/(q->w.in*q->soft_treshold),
                              pd->w.in>=(double)q->soft_treshold/100*q->w.in?'-':'+');
                  if (q->w.in)
                        cli_print(cli, "  WEEK   in: %s, hardquota %s ratio %.0f%% -> [%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.out && q->soft_treshold)
                        cli_print(cli, "  WEEK  out: %s, softquota %s ratio %.0f%% -> [%c]",
                              bytesQ2T(pd->w.out, buf),
                              bytesQ2T(q->soft_treshold*q->w.out/100, buf2),
                              10000*(double)pd->w.out/(q->w.out*q->soft_treshold),
                              pd->w.out>=(double)q->soft_treshold/100*q->w.out?'-':'+');
                  if (q->w.out)
                        cli_print(cli, "  WEEK  out: %s, hardquota %s ratio %.0f%% -> [%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.sum && q->soft_treshold)
                        cli_print(cli, "  WEEK  sum: %s, softquota %s ratio %.0f%% -> [%c]",
                              bytesQ2T(pd->w.in+pd->w.out, buf),
                              bytesQ2T(q->soft_treshold*q->w.sum/100, buf2),
                              10000*(double)(pd->w.in+pd->w.out)/(q->w.sum*q->soft_treshold),
                              (pd->w.in+pd->w.out)>=(double)q->soft_treshold/100*q->w.sum?'-':'+');
                  if (q->w.sum)
                        cli_print(cli, "  WEEK  sum: %s, hardquota %s ratio %.0f%% -> [%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.in && q->soft_treshold)
                        cli_print(cli, "  MONTH  in: %s, softquota %s ratio %.0f%% -> [%c]",
                              bytesQ2T(pd->m.in, buf),
                              bytesQ2T(q->soft_treshold*q->m.in/100, buf2),
                              10000*(double)pd->m.in/(q->m.in*q->soft_treshold),
                              pd->m.in>=(double)q->soft_treshold/100*q->m.in?'-':'+');
                  if (q->m.in)
                        cli_print(cli, "  MONTH  in: %s, hardquota %s ratio %.0f%% -> [%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.out && q->soft_treshold)
                        cli_print(cli, "  MONTH out: %s, softquota %s ratio %.0f%% -> [%c]",
                              bytesQ2T(pd->m.out, buf),
                              bytesQ2T(q->soft_treshold*q->m.out/100, buf2),
                              10000*(double)pd->m.out/(q->m.out*q->soft_treshold),
                              pd->m.out>=(double)q->soft_treshold/100*q->m.out?'-':'+');
                  if (q->m.out)
                        cli_print(cli, "  MONTH out: %s, hardquota %s ratio %.0f%% -> [%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.sum && q->soft_treshold)
                        cli_print(cli, "  MONTH sum: %s, softquota %s ratio %.0f%% -> [%c]",
                              bytesQ2T(pd->m.in+pd->m.out, buf),
                              bytesQ2T(q->soft_treshold*q->m.sum/100, buf2),
                              10000*(double)(pd->m.in+pd->m.out)/(q->m.sum*q->soft_treshold),
                              (pd->m.in+pd->m.out)>=(double)q->soft_treshold/100*q->m.sum?'-':'+');
                  if (q->m.sum)
                        cli_print(cli, "  MONTH sum: %s, hardquota %s ratio %.0f%% -> [%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);
            }
         }//quotas
      } //units
//    if(err2!=EDEADLK) netams_rwlock_unlock(&Units->rwlock);
//    if(err1!=EDEADLK) netams_rwlock_unlock(&cfg->rwlock);
      cli_print(cli, "Total units: %u, enabled: %u, active: %u, blocked: %u, softblocked: %u\n",
            total, enabled, active, blocked, softblocked);

      return CLI_OK;
}

//////////////////////////////////////////////////////////////////////////////////////////
int cQuotaSet(struct cli_def *cli, const char *cmd, char **param, int argc){
      NetUnit *u;
      Policy *p=NULL;
      u_char i=1;
      sQuotaData *q=NULL;

      Service_Quota *sq=(Service_Quota*)Quota;
      if(!sq) {
            cli_print(cli, "Service quota not enabled");
            return CLI_OK;
      }

      u=aParseUnit(param, &i);
      if(u==NULL) {
            cli_error(cli, "unit not exist");
            return CLI_OK;
      }

      if (STRARG(param[i], "policy")) {
            i++;
            p=aParsePolicy(param, &i);
            for(q=u->quotadata;q!=NULL; q=q->next)
                  if(q->policy == p) break;
      } else
            q=u->quotadata;

      if (q==NULL) {
            q= (sQuotaData*)aMalloc(sizeof(sQuotaData));
            q->flags=QUOTA_ACTIVE;
            q->blocked_time=0L;
            if(p)
                  q->policy = p;
            else
                  q->policy = sq->default_policy;
            q->fw_block_policy=NULL;
            q->fw_block_policy_flags=0;
            q->soft_treshold= sq->default_soft_treshold;
            if(sq->notify_soft[0]) {
                  q->flags|=QUOTA_NSS;
                  q->nso=sq->notify_soft[1];
            }
            if(sq->notify_hard[0]) {
                  q->flags|=QUOTA_NHS;
                  q->nho=sq->notify_hard[1];
            }
            if(sq->notify_return[0]) {
                  q->flags|=QUOTA_NRS;
                  q->nro=sq->notify_return[1];
            }

            q->next = u->quotadata;
            u->quotadata=q;
            cli_error(cli, "Creating quotadata to unit %s, policy %s", u->name, q->policy->name);
      } else
            cli_error(cli, "Configuring quota for unit %s, policy %s", u->name, q->policy->name);

      for(;i<argc; i+=2)  {
            if (STRARG(param[i], "block-policy")) {
                  Policy *p;
                  policy_flag flags=POLICY_FLAG_NONE;
                  char *c_param=param[i+1];

                  if (c_param[0]=='!') { flags|=POLICY_FLAG_INV; c_param++; }
                  if (c_param[0]=='%') { flags|=POLICY_FLAG_BRK; c_param++; }
                  if (c_param[0]=='!') { flags|=POLICY_FLAG_INV; c_param++; }

                  if ((p=PolicyL->getPolicy(c_param))) {
                        q->fw_block_policy=p;
                        q->fw_block_policy_flags=flags;
                        cli_error(cli, "unit %06X block policy set to %s%s%s",
                              u->id, (flags&POLICY_FLAG_INV)?"!":"",
                              (flags&POLICY_FLAG_BRK)?"%":"", c_param);
                  } else
                        cli_error(cli, "no such policy exist: %s", param[i+1]);
            }
            else if (STRARG(param[i], "soft-treshold")) {
                  u_char st=strtol(param[i+1], NULL, 10);
                  if (st>100) {
                        cli_error(cli, "invalid soft treshold value: %u (must be betwaan 0 and 100)", st);
                  }
                  else {
                        cli_error(cli, "soft treshold set to %u", st);
                        q->soft_treshold=st;
                  }
            }
            else if (STREQ(param[i], "active")) {
                  cli_error(cli, "unit %06X quota is set to ACTIVE", u->id);
                  q->flags|=QUOTA_ACTIVE;
                  if (q->flags&QUOTA_BLOCKED)
                        sq->QuotaAction(u, q, ADD, time(NULL));
                  i--;
            }
            else if (STREQ(param[i], "inactive")) {
                  cli_error(cli, "unit %06X quota is set to INACTIVE", u->id);
                  q->flags&=~QUOTA_ACTIVE;
                  if (q->flags&QUOTA_BLOCKED)
                        sq->QuotaAction(u, q, REMOVE, time(NULL));
                  i--;
            }
            else if (STREQ(param[i], "notify")) {
                  User *us;
                  u_char j=i+2;
                  if (STRARG(param[i+1], "soft")) {
                        if (STREQ(param[j], "none")) {
                              q->flags&=~QUOTA_NSS;
                              q->nso=0;
                        }
                        if (STREQ(param[j], "owner")) {
                              q->flags|=QUOTA_NSS;
                              j++;
                        }
                        us=Users->getUser(param[j]);
                        if (us)
                              q->nso=us->id;
                  }
                  if (STRARG(param[i+1], "hard")) {
                        if (STREQ(param[j], "none")) {
                              q->flags&=~QUOTA_NHS;
                              q->nho=0;
                        }
                        if (STREQ(param[j], "owner")){
                              q->flags|=QUOTA_NHS;
                              j++;
                        }
                        us=Users->getUser(param[j]);
                        if (us)
                              q->nho=us->id;
                  }
                  if (STRARG(param[i+1], "return")) {
                        if (STREQ(param[j], "none")){
                              q->flags&=~QUOTA_NRS;
                              q->nro=0;
                        }
                        if (STREQ(param[j], "owner")){
                              q->flags|=QUOTA_NRS;
                              j++;
                        }
                        us=Users->getUser(param[j]);
                        if (us)
                              q->nro=us->id;
                  }
                  i=j;
            }
            else if (STRARG(param[i], "hour"))
                  sQuotaGetValue(&i, param, &(q->h));
            else if (STRARG(param[i], "day"))
                  sQuotaGetValue(&i, param, &(q->d));
            else if (STRARG(param[i], "week"))
                  sQuotaGetValue(&i, param, &(q->w));
            else if (STRARG(param[i], "month"))
                  sQuotaGetValue(&i, param, &(q->m));
      } //for

      aDebug(DEBUG_QUOTA, "set/got: oid=%06X\n", u->id);

      q->flags|=QUOTA_UPDATE; //needs update

      Quota->Wakeup();
      return CLI_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////
int cQuotaNotify(struct cli_def *cli, const char *cmd, char **param, int argc){
      Service_Quota *sq=(Service_Quota*)Quota;
      User *us;
      u_char j=2;

      netams_rwlock_wrlock(&sq->rwlock);

      if (STRARG(param[1], "soft")) {
            if (STREQ(param[j], "owner")){
                  sq->notify_soft[0]=1;
                  j++;
            }
            us=Users->getUser(param[j]);
            if (us) {
                  sq->notify_soft[1]=us->id;
                  cli_error(cli, "notify soft set to %s", param[j]);
            } else
                  cli_error(cli, "no such user exist: %s", param[j]);

      } else if (STRARG(param[1], "hard")) {
            if (STREQ(param[j], "owner")){
                  sq->notify_hard[0]=1;
                  j++;
            }
            us=Users->getUser(param[j]);
            if (us) {
                  sq->notify_hard[1]=us->id;
                  cli_error(cli, "notify hard set to %s", param[j]);
            } else
                  cli_error(cli, "no such user exist: %s", param[j]);

      } else if (STRARG(param[1], "return")) {
            if (STREQ(param[j], "owner")){
                  sq->notify_return[0]=1;
                  j++;
            }
            us=Users->getUser(param[j]);
            if (us) {
                  sq->notify_return[1]=us->id;
                  cli_error(cli, "notify return set to %s", param[j]);
            } else
                  cli_error(cli, "no such user exist: %s", param[j]);
      }
      netams_rwlock_unlock(&sq->rwlock);
      return CLI_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////
void sQuotaGetValue(u_char *i, char *param[], qstat *q){

      u_char j=*i+1;
      unsigned long long data;
      while (1) {
            if (param[j]!=NULL && param[j][0]=='-') break; /* we have negative value requested: abort whole request */
            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;
}
//////////////////////////////////////////////////////////////////////////
void sQuSendAlert(NetUnit *u, sQuotaData *q, u_char dir){  // dir=1:violates; =0:back; =2:soft_quota_reached
      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;
      al->user_id[0]=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);

      Service *s=Quota;
      if(!s) return;

      //we do not need lock here because we locked it in sQuota already

      switch (dir) {
            case 0:
                  if (q->flags&QUOTA_NRS) { al->unit_id[0]=u->id; }
                  al->user_id[0]=q->nro;
                  print_to_string(&subject, "Quota: unit %s quota RETURN", u->name?u->name:"<>");
                  print_to_string(&message, "NeTAMS Quota service have detected quota RETURN for unit %s (%06X)\n", u->name?u->name:"<>", u->id);
                  break;
            case 1:
                  if (q->flags&QUOTA_NHS) { al->unit_id[0]=u->id; }
                  al->user_id[0]=q->nho;
                  print_to_string(&subject, "Quota: unit %s quota VIOLATION", u->name?u->name:"<>");
                  print_to_string(&message, "NeTAMS Quota service have detected quota HARD REACH for unit %s (%06X)\n", u->name?u->name:"<>", u->id);
                  break;
            case 2:
                  if (q->flags&QUOTA_NSS) { al->unit_id[0]=u->id; }
                  al->user_id[0]=q->nso;
                  print_to_string(&subject, "Quota: unit %s quota SOFT REACH", u->name?u->name:"<>");
                  print_to_string(&message, "NeTAMS Quota service have detected quota SOFT REACH for unit %s (%06X)\n", u->name?u->name:"<>", u->id);
                  break;
      }

      if (!(al->unit_id[0] | al->user_id[0])) { // no recipients, discard this alert
            aFree(subject); aFree(message);
            delete msg;
            aDebug(DEBUG_ALERT, "alert (quota) abandoned because of no recipients\n");
            return;
      }

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

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

      Service_Html *html= Html;
      if (html) {
            print_to_string(&message, "\n##############################################################");
            print_to_string(&message, "\nYou can check your traffic statistics online by clicking here:\n");
            print_to_string(&message, "%s/clients/%s/index.html\n\n", html->url, u->name);
      }
      al->data=NULL;
      print_to_string(&al->data, "%s\n%s\n", subject, message);


      // dirty hack - send SMS
      if (al->user_id[0]) {
          User *uu=(User*)Users->getById(al->user_id[0]);
            if (uu && uu->sms) {
                char *data=NULL;
                print_to_string(&data, "/usr/local/bin/sendsms %s \"%s: [%s]\"", uu->sms, subject, u->description?u->description:"");
                aDebug(DEBUG_ALERT, "alert (quota SMS) \"%s\"\n", data);
                system(data);
                aFree(data);
            }
      }

      aFree(subject); aFree(message);

      aDebug(DEBUG_ALERT, "alert (quota) %u complete, data is %u bytes\n", al->alert_id, strlen(al->data));
      alerter->ProcessMessage(msg);
}
//////////////////////////////////////////////////////////////////////////
void FillQuotaData(void *res, void *row, char* (*getRowData)(void*, void* , u_char)) {
        sQuotaData *q;
        unsigned tmp;
        NetUnit *u=NULL;
        oid id;

        sscanf(getRowData(res, row, 0), "%u", &id);
        if(id && !(u=(NetUnit*)Units->getById(id))) return;

        q = (sQuotaData*)aMalloc(sizeof(sQuotaData));
        q->next = u->quotadata;
        u->quotadata = q;

        sscanf(getRowData(res, row, 1), "%u", &id); q->policy=(Policy*)PolicyL->getById(id);
        sscanf(getRowData(res, row, 3), "%u", &tmp); q->soft_treshold=tmp;
        sscanf(getRowData(res, row, 4), "%u", &tmp); q->flags=tmp;
        sscanf(getRowData(res, row, 5), "%lu", (unsigned long*)&q->blocked_time);

        sscanf(getRowData(res, row, 6), "%u", &q->nso);
        sscanf(getRowData(res, row, 7), "%u", &q->nho);
        sscanf(getRowData(res, row, 8), "%u", &q->nro);

        sscanf(getRowData(res, row, 9), "%llu", &q->h.in);
        sscanf(getRowData(res, row, 10), "%llu", &q->h.out);
        sscanf(getRowData(res, row, 11), "%llu", &q->h.sum);

        sscanf(getRowData(res, row, 12), "%llu", &q->d.in);
        sscanf(getRowData(res, row, 13), "%llu", &q->d.out);
        sscanf(getRowData(res, row, 14), "%llu", &q->d.sum);

        sscanf(getRowData(res, row, 15), "%llu", &q->w.in);
        sscanf(getRowData(res, row, 16), "%llu", &q->w.out);
        sscanf(getRowData(res, row, 17), "%llu", &q->w.sum);

        sscanf(getRowData(res, row, 18), "%llu", &q->m.in);
        sscanf(getRowData(res, row, 19), "%llu", &q->m.out);
        sscanf(getRowData(res, row, 20), "%llu", &q->m.sum);

        sscanf(getRowData(res, row, 21), "%u", &id);

        if (id)
                q->fw_block_policy=(Policy*)PolicyL->getById(id);
        else
                q->fw_block_policy=NULL;

        sscanf(getRowData(res, row, 22), "%u", &tmp);
        q->fw_block_policy_flags=tmp;

        u->quotadata=q;
        aDebug(DEBUG_QUOTA, "Unit: %06X soft %d flags %d\n", u->id, q->soft_treshold, q->flags);
}
//////////////////////////////////////////////////////////////////////////////////////////


Generated by  Doxygen 1.6.0   Back to index