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

s_datasource.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_datasource.c,v 1.212 2009-08-01 09:23:54 anton Exp $ */

#include "netams.h"
#include "ds_any.h"

static int initialized=0;

//////////////////////////////////////////////////////////////////////////
void sDSRuleIp(Service_DS *s, char *rule, u_short number, u_short flag);
void NFSourceAdd(Service_DS *s, char **param, u_char no_flag);
//////////////////////////////////////////////////////////////////////////

void* ds_worker(void *ss);
//ds's we support
void ds_ipq(Service_DS *ds);
void ds_ulog(Service_DS *ds);
void ds_ipfw(Service_DS *ds);
void ds_netgraph(Service_DS *ds);
void ds_netflow(Service_DS *ds);
void ds_libpcap(Service_DS *ds);
void ds_raw(Service_DS *ds);
//void ds_mail(Service_DS *ds);

extern void ds_libpcap_stats(struct cli_def *cli, Service_DS *s);
extern void ds_netgraph_stats(struct cli_def *cli, Service_DS *s);
/////////////////////////////////////////////////////////////////////////
int cShowDS       (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, "ds",  PRIVILEGE_UNPRIVILEGED, MODE_EXEC, cShowDS,           "data-source services status" },
{ 12, 0, 0, "type",     PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, NULL,              NULL },
{ 0, 12, 0, "ip-traffic", PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,    NULL },
{ 0, 12, 0, "raw", PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,     NULL },
#ifdef FREEBSD
{ 0, 12, 0, "netgraph", PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },
#endif
{ 0, 12, 0, "netflow",  PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },
#ifndef NOPCAP
{ 0, 12, 0, "libpcap",  PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },
#endif
{ 0, 0, 1, "rule",      PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },
{ 15, 0, 0, "source",   PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },
#ifdef LINUX
{ 0, 15, 0, "ipq",      PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },
{ 0, 15, 0, "ulog",     PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },
#elif FREEBSD
{ 0, 15, 0, "tee",      PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },
{ 0, 15, 0, "divert",   PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },
#endif
{ 43, 0, 0, "layer7-detect",  PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, NULL,        NULL },
{ 0, 43, 0, "none",     PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },
{ 0, 43, 43, "urls",    PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },

{ 0, 0, 0, "listen",    PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },
{ 13, 0, 0, "clock",    PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, NULL,              NULL },
{ 0, 13, 0, "local",    PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },
{ 0, 13, 0, "remote",   PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceProcessCfg,      NULL },
{ 0, 0, 0, "start",     PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceStart,         NULL },
{ 0, 0, 0, "stop",      PRIVILEGE_UNPRIVILEGED, MODE_DATASOURCE, cServiceStop,          NULL },
{ -1, 0, 0, NULL,  0, 0, NULL, NULL }
};
//////////////////////////////////////////////////////////////////////////////////////////
Service* InitDatasourceService() {
        if(!initialized) {
                InitCliCommands(cmd_db);
                initialized = 1;
        }
        return (Service*)new Service_DS();
}
//////////////////////////////////////////////////////////////////////////
Service_DS::Service_DS(): Service_Datasource_Interface() {
      pt_type=PT_UNKNOWN;
      
      ds_flags=DS_NONE;

      total_packets=0;
      total_flows=0;
      total_errors=0;
      timestamp=0;

      root=NULL;
      src_cmd=NULL;
      
      //netflow
      l_addr.s_addr=INADDR_ANY;
      port=0;
      nfroot=NULL;

      //libpcap
      pcap_data=NULL;
      
      //ulog
      nlmask=0;

      delay=skewdelay=0;
      pc=bc=tc=ptc=0;

      ds_fifo = new DS_FIFO(10000);
      IPtree = NULL;
      FE = NULL;
      msg = NULL;
        ds_flow = NULL;

      max_flow_slots = 1;

      packet=(unsigned char*)aMalloc(MAX_PKT_SIZE);

      layer7_detect = LAYER7_DETECT_NONE;

      child=NULL;
      ds_func=NULL;
}

Service_DS::~Service_DS () {
      ds_rule *t=NULL;
      while(root) {
            t=root;
            root=root->next;
            if(t->rule_str) aFree(t->rule_str);
            aFree(t);
      }
      
      if(child) delete child;
      if(FE) delete FE;
      if(ds_fifo) delete ds_fifo;
      if(ds_flow) delete ds_flow;

      delete IPtree;

      for(NFSource *tmp = nfroot; nfroot!=NULL;) {
            tmp=nfroot;
            nfroot=nfroot->next;
            aFree(tmp);
      }

      if(pcap_data) aFree(pcap_data);
      if(packet) aFree(packet);
      if(src_cmd) aFree(src_cmd);
}
//////////////////////////////////////////////////////////////////////////
int Service_DS::ProcessCfg(struct cli_def *cli, char **param, int argc, u_char no_flag){
      char buffer[32];

      if (STREQ(param[0], "type")) {
            if (STREQ(param[1], "ip-traffic")) {
                  cli_error(cli, "data-source type is set to ip-traffic");
                  pt_type=PT_IP_TRAFFIC;
                  max_flow_slots=3;
#ifdef LAYER7_FILTER
                  max_flow_slots++;
#endif
            }
#ifdef FREEBSD
#ifndef MACOS
            else if (STREQ(param[1], "netgraph")) {
                  cli_error(cli, "data-source type is set to netgraph");
                  pt_type=PT_NETGRAPH;
                  max_flow_slots=4;
            }
#endif      
#endif      
            else if (STREQ(param[1], "netflow")) {
                  cli_error(cli, "data-source type is set to cisco NetFlow");
                  pt_type=PT_NETFLOW_TRAFFIC;
                  if (!port) port=20001;
                  if(src_cmd) aFree(src_cmd);
                  src_cmd=set_string("0.0.0.0");
                  max_flow_slots=5;
            }
#ifndef NOPCAP
            else if (STREQ(param[1], "libpcap")) {
                  cli_error(cli, "data-source type is set to libpcap");
                  pt_type=PT_LIBPCAP_TRAFFIC;
                  max_flow_slots=4;
#ifdef LAYER7_FILTER
                  max_flow_slots++;
#endif
            }
#endif
            else if (STREQ(param[1], "raw")) {
                  cli_error(cli, "data-source type is set to raw");
                  pt_type=PT_RAW;
                  max_flow_slots=1;
            }
      }
      else if (STRARG(param[0], "rule")) {
            unsigned number=strtol(param[1], NULL, 10);
            ds_rule *t=NULL, *tt=NULL;

            for (t=root; t!=NULL; t=t->next) {
                  if (t->number==number) break;
                  tt=t;
            }

            if (no_flag && t) {
                  cli_error(cli, "rule %d removed", number);
                  sDSRuleIp(this, t->rule_str, number, REMOVE);
                  if( t->rule_str) aFree(t->rule_str);
                  if(root==t) root=t->next;
                  else tt->next=t->next;
                  aFree(t);
            } //chain removal!!!!!!!
            else if (!no_flag && t) {
                  sDSRuleIp(this, t->rule_str, number, REMOVE);
                  if(t->rule_str) aFree(t->rule_str);
                  t->rule_str=set_string(param[2]);
                  cli_error(cli, "rule %d replaced to %s", number, t->rule_str);
                  sDSRuleIp(this, t->rule_str, number, ADD);
            }
            else if (!t) {
                  t=(ds_rule*)aMalloc(sizeof(ds_rule));
                  t->rule_str=set_string(param[2]);
                  t->number=number;
                  t->next=NULL;
                  if(root) tt->next=t; else root=t;
                  cli_error(cli, "rule %d set to %s", number, t->rule_str);
                  sDSRuleIp(this, t->rule_str, number, ADD);
            }
      }
      else if (STREQ(param[0], "source")) {
            if(0);
#if defined(LINUX)
            else if (STREQ(param[1], "ipq")) {
                  src_cmd=set_string("ipq");
                  ds_flags=DS_IPQ;
                  cli_error(cli, "source is set to ipq");
            }
            else if (STRARG(param[1], "ulog")) {
                  unsigned tmp_nlmask=0;
                  u_char i=2;
                  for(; i<argc && isdigit(param[i][0]); i++) {
                        u_char tmp_nlgroup=strtol(param[i], NULL, 10);
                        if(tmp_nlgroup<1 || tmp_nlgroup>32)
                              cli_error(cli, "nlgroup has to be between 1 and 32");
                        else 
                              tmp_nlmask|=(1<<(tmp_nlgroup-1));
                  }
                  if(tmp_nlmask && tmp_nlmask!=nlmask) {
                        if(src_cmd) aFree(src_cmd);
                        src_cmd=set_string("ulog");
                        nlmask=tmp_nlmask;
                        ds_flags=DS_ULOG;
                        cli_error(cli, "source is set to ulog, nlmask=%u", nlmask);
                  }
        }
#endif
#if defined(FREEBSD)
            else if (STRARG(param[1], "tee")) {
                  unsigned short tport=strtol(param[2], NULL, 10);
                  if (!tport) tport=199;
                  cli_error(cli, "source is set to tee:%u", tport);
                  src_cmd=set_string("tee");
                  port=tport;
                  ds_flags=DS_TEE;
            }
            else if (STRARG(param[1], "divert")) {
                  unsigned short tport=strtol(param[2], NULL,10);
                  if (!port) tport=199;
                  cli_error(cli, "source is set to divert:%u", tport);
                  src_cmd=set_string("divert");
                  port=tport;
                  ds_flags=DS_DIVERT;
            }
#endif
            else if (pt_type == PT_NETFLOW_TRAFFIC && param[1]) {
                  if(INADDR_BROADCAST!=inet_addr(param[1])) {
                        NFSourceAdd(this, &param[1], no_flag);
                        cli_error(cli, "%s %s source %s accept list", (no_flag)?"Removing":"Adding", param[1],(no_flag)?"from":"to");
                  }
            }
            else if (pt_type==PT_LIBPCAP_TRAFFIC && param[1]) {
                  cli_error(cli, "source is listening interface %s", param[1]);
                  src_cmd=set_string(param[1]);
                  port=0;
                  if(STREQ(param[2], "promisc")) ds_flags=DS_PROMISC;
                  else ds_flags=DS_NONE;
            }
#ifdef FREEBSD
#ifndef MACOS
            else if (pt_type==PT_NETGRAPH && param[1]) {
                  cli_error(cli, "source is listening node %s", param[1]);
                  src_cmd=set_string(param[1]);
                  port=0;
                  if(STREQ(param[2], "divert")) ds_flags=DS_DIVERT;
                  else ds_flags=DS_TEE;
            }
#endif
#endif
            else 
                  cli_error(cli, "source is invalid or not available");
      }
      else if (STREQ(param[0], "clock")) {
            if(pt_type == PT_NETFLOW_TRAFFIC) {
                  if (STREQ(param[1], "remote")) {
                        cli_error(cli, "using remote flow time");
                        ds_flags=DS_CLOCK_REMOTE;
                  } else if (STREQ(param[1], "local")) {
                        cli_error(cli, "using local time");
                        ds_flags=DS_NONE;
                  } else {
                        cli_error(cli, "Clock undefined! Defaulting to local time");
                        ds_flags=DS_NONE;
                  }
            } else {
                  cli_error(cli, "Setting clock undefined for this data-source type");
            }
      }
      else if (STRARG(param[0], "listen")) {
            if (pt_type == PT_NETFLOW_TRAFFIC) {
                  if(INADDR_BROADCAST!=inet_addr(param[1])) {
                        inet_aton(param[1], &l_addr);
                        if(argc>2) port=strtol(param[2], NULL, 10);
                        if(src_cmd) aFree(src_cmd);
                        src_cmd=set_string(param[1]);
                        cli_error(cli, "listening %s:%u",
                              inet_ntop(AF_INET, &(l_addr), buffer, 32), port);
                  } else {
                        cli_error(cli, "Command listen undefined for this data-source type");
                  }
            }
      }
#ifdef LAYER7_FILTER
      else if (STRARG(param[0], "layer7-detect")) {
            if (pt_type == PT_LIBPCAP_TRAFFIC || pt_type == PT_IP_TRAFFIC) {
                  if (STREQ(param[1], "none")) {
                        cli_error(cli, "do not detect any type of layer7 traffic");
                        layer7_detect=LAYER7_DETECT_NONE;
                  } else if (STREQ(param[1], "urls")) {
                        cli_error(cli, "detect URLs");
                        layer7_detect=LAYER7_DETECT_URLS;
                  } else cli_error(cli, "layer7-detect parameter unknown");
            } else cli_error(cli, "layer7-detect will not work for this data-source type");
      }
#endif
      return CLI_OK;
}
//////////////////////////////////////////////////////////////////////////
void* ds_worker(void* ss){
      Service_DS      *ds                     = (Service_DS*)ss;

        ds->ds_func(ds);

      //if we here error ocurs
      aLog(D_ERR, "Data-source %s:%u error starting child thread\n", ds->getName(), ds->instance);
      pthread_cancel(ds->t_id);
      return NULL;
}
//////////////////////////////////////////////////////////////////////////
void Service_DS::Worker(){
      u_char            fw_check          = 0;
      service_type      ds_type                 = SERVICE_UNDEF;

      switch (pt_type) {
            case PT_IP_TRAFFIC:     // here we are assume that arrived data has an IP format
                  #if defined(LINUX) && !defined(IPTBL_NONE)
                  if(ds_flags==DS_IPQ) {
                        fw_check = 1;
                        ds_type      = SERVICE_DS_IPQ;       
                        ds_func      = &ds_ipq;             
                  } else {
                        ds_type  = SERVICE_DS_ULOG;
                        ds_func  = &ds_ulog;
                  }
                  #endif
                  #ifdef FREEBSD
                        fw_check = (ds_flags==DS_DIVERT);
                        ds_type  = SERVICE_DS_IPFW;
                        ds_func  = &ds_ipfw;
                  #endif
                  break;
            case PT_NETFLOW_TRAFFIC:
                  ds_type  = SERVICE_DS_NETFLOW;
                  ds_func  = &ds_netflow;
                  break;
#ifndef NOPCAP
            case PT_LIBPCAP_TRAFFIC:
                  ds_type  = SERVICE_DS_LIBPCAP;
                  ds_func  = &ds_libpcap;
                  break;
#endif
#ifdef FREEBSD
#ifndef MACOS
            case PT_NETGRAPH: 
                  ds_type  = SERVICE_DS_NETGRAPH;
                  ds_func  = &ds_netgraph;
                  break;
#endif
#endif
            case PT_RAW: 
                  ds_type  = SERVICE_DS_RAW;
                  ds_func  = &ds_raw;
                  break;
            default:    // this source type is not catched yet!
                  aLog(D_ERR, "Data-source:%u type is undefined or not compiled\n", instance);
                  return;
      }

      if(!IPtree) IPtree = new IPTree(instance);

      //init units for this datasource
      netams_rwlock_wrlock(&Units->rwlock);
      for (NetUnit *u=(NetUnit*)Units->root; u!=NULL; u=(NetUnit*)u->next)
            if(u->checkDSList(this->instance))
                  u->unit2ds(this, ADD);
      netams_rwlock_unlock(&Units->rwlock);
            
      if(!FE)           FE = new FlowEngine(this);
      
      FE->InitFW(fw_check);
      
      child=new Service(ds_type, instance);
      Services->Insert(child);
      
      pthread_create(&(child->t_id), NULL, ds_worker, (void*)this);

      while(1) {
            AcctFlows();
            Sleep(1);
      }
}
//////////////////////////////////////////////////////////////////////////
void Service_DS::Cancel(){
      for(ds_rule *t=root; t!=NULL; t=t->next) {
//          printf("removing %p (%p) %d %s\n", t, t->next, t->number, t->rule_str);
            sDSRuleIp(this, t->rule_str, t->number, REMOVE);
      }
      if(child) {
            child->Stop();
            Services->Delete(child);
            delete child;
            child =NULL;
      }

      if(ds_fifo) {
            if(FE) FE->FlushAll();
            aLog(D_INFO, "cancelling service data-source:%u, flushing %u messages\n",
                  instance, ds_fifo->num_items);
            AcctFlows();  //ensure we count collected data
      }

      while(nfroot) {
            NFSource *nf;
            nf=nfroot;
            nfroot=nf->next;

            for(u_short i=0; i<nf->nfTemplate_num; i++) {
                  struct NetFlowV9Template *nftmpl = nf->nfTemplate[i];
                  if(nftmpl->fields)
                        aFree(nftmpl->fields);
                  aFree(nftmpl);
            }
            if(nf->nfTemplate) aFree(nf->nfTemplate);
            aFree(nf);
      }
}
//////////////////////////////////////////////////////////////////////////
void Service_DS::ShowCfg(struct cli_def *cli, u_char flags){
      char buffer[32];

      if (pt_type==PT_IP_TRAFFIC){
            cli_print(cli, "type ip-traffic");
            cli_bufprint(cli, "source %s", src_cmd);

            if(ds_flags==DS_ULOG) {
                  for(u_char i=0;i<32;i++) {
                        if(nlmask&(1<<i))
                              cli_bufprint(cli, " %u", i+1);
                  }
            } 
            else if (ds_flags==DS_TEE || ds_flags==DS_DIVERT)
                  cli_bufprint(cli, " %u", port);
            
            cli_bufprint(cli, "\n");
      }
      else if (pt_type==PT_NETFLOW_TRAFFIC) {
            in_addr ina;

            cli_print(cli, "type netflow");
            if (l_addr.s_addr != INADDR_ANY || port!=20001) 
                  cli_print(cli, "listen %s %u", inet_ntop(AF_INET, &(l_addr), buffer, 32), port);
            for(NFSource *nf=nfroot; nf!=NULL; nf=nf->next) {
                  ina.s_addr=nf->src_addr;
                  cli_bufprint(cli, "source %s", inet_ntop(AF_INET, &ina, buffer, 32));
                  if(nf->engine_id) cli_bufprint(cli, " engine %u", nf->engine_id);
                  cli_bufprint(cli, "\n");
            }
            if (ds_flags==DS_CLOCK_REMOTE)
                  cli_print(cli, "clock remote");
            return;
      }
      else if (pt_type==PT_LIBPCAP_TRAFFIC){
            cli_print(cli, "type libpcap");
            cli_print(cli, "source %s %s", src_cmd, (ds_flags==DS_PROMISC)?"promisc":"");
      }
      else if (pt_type==PT_NETGRAPH){
            cli_print(cli, "type netgraph");
            cli_print(cli, "source %s %s", src_cmd, (ds_flags==DS_DIVERT)?"divert":"");
      }
      
      else if (pt_type==PT_RAW){
            cli_print(cli, "type raw");
      }

      if (layer7_detect!=LAYER7_DETECT_NONE){
            if (layer7_detect==LAYER7_DETECT_URLS) cli_print(cli, "layer7-detect urls");
      }

      for (ds_rule *r=root; r!=NULL; r=r->next) 
            if (r->rule_str)
                  cli_print(cli, "rule %u \"%s\"", r->number, r->rule_str);
      
}
//////////////////////////////////////////////////////////////////////////
void sDSRuleIp(Service_DS *ds, char *rule, u_short number, u_short flag) {
      
      if (ds->pt_type==PT_IP_TRAFFIC) {
            char buffer[255];
            
            switch (flag) {
            case ADD: // add a rule to the system
                  #ifdef LINUX
                  sprintf(buffer,"/sbin/iptables -I %s 2>&1 >/dev/null", rule);
                  #else
                  sprintf(buffer,"/sbin/ipfw add %u %s %u %s 2>&1 >/dev/null", number, ds->src_cmd, ds->port, rule);
                  #endif
                  
                  break;
            case REMOVE:  // remove a rule from the system
                  #ifdef LINUX
                  sprintf(buffer, "/sbin/iptables -D %s 2>&1 >/dev/null", rule);
                  #else
                  sprintf(buffer,"/sbin/ipfw delete %u 2>&1 >/dev/null", number);
                  #endif
                  break;
            default: 
                  break;
            }
            system(buffer);
      }
      aLog(D_INFO, "%s rule %u \"%s\"\n", (flag==ADD)?"adding":"removing", number, rule);
}
//////////////////////////////////////////////////////////////////////////
void NFSourceAdd(Service_DS *s, char **param, u_char no_flag) {
      NFSource *nf, *p=NULL;
      in_addr ina;
      unsigned engine_id = 0;
      
      inet_aton(param[0], &ina);
      
      if(STRARG(param[1], "engine")) {
            engine_id = strtol(param[2], NULL, 10); 
      }

      for(nf=s->nfroot; nf!=NULL; nf=nf->next) {
            if(nf->src_addr==ina.s_addr 
            && (!engine_id || !nf->engine_id || engine_id == nf->engine_id) )
                   break;
            p=nf;
      }

      if(no_flag) { //REMOVE
            if(!nf) return;
            if(s->nfroot==nf) s->nfroot=s->nfroot->next;
            else p->next=nf->next;
            for(u_short i=0; i<nf->nfTemplate_num; i++) {
                  struct NetFlowV9Template *nftmpl = nf->nfTemplate[i];
                  if(nftmpl->fields)
                        aFree(nftmpl->fields);
                  aFree(nftmpl);
            }
            if(nf->nfTemplate) aFree(nf->nfTemplate);
            aFree(nf);
      } else { //ADD
            if(nf) return;
            nf=(NFSource*)aMalloc(sizeof(NFSource));
            nf->src_addr=ina.s_addr;
            nf->engine_id = engine_id;
            if(s->nfroot==NULL) s->nfroot=nf;
            else p->next=nf;
      }
}
//////////////////////////////////////////////////////////////////////////
int cShowDS(struct cli_def *cli, const char *cmd, char **argv, int argc){
        Service *s=NULL;
      char buffer[32];

        while((s=Services->getServiceNextByType(SERVICE_DATASOURCE,s))) {
            Service_DS *ds=(Service_DS*)s;
            
            ds->ShowInfo(cli);

            //show IP tree
            IPTree *IPtree=ds->IPtree;
            if(IPtree) {
                  cli_print(cli, "    IP tree: %lu nodes [%u] + %lu dlinks [%u] + %lu unodes [%u] = %lu bytes",
                  IPtree->nodes,sizeof(IPTree_node),
                  IPtree->dlink,256*sizeof(IPTree_node*),
                  IPtree->unodes,sizeof(dsUlist),
                  IPtree->nodes*sizeof(IPTree_node)+IPtree->dlink*256*sizeof(IPTree_node*)+IPtree->unodes*sizeof(dsUlist));
            }
            //show flow
            FlowEngine *FE=ds->FE;
            if(FE &&
                  //this actually doesnt use FlowEngine completely, only DoSend() call.
                  !(ds->pt_type==PT_NETFLOW_TRAFFIC   || ds->pt_type==PT_NETGRAPH)
            ) {
                  cli_print(cli, "    Flows: %u/%u act/inact entries (%u bytes), %llu flows sent",
                        FE->e_used,
                        FE->e_total-FE->e_used,
                        FE->e_total*(sizeof(entry)+sizeof(Flow)+sizeof(struct attribute)*ds->max_flow_slots),
                        FE->sent_flows);
                  //show hash
                  //gather flow hash statistic
                  entry *e;
                  unsigned used=0;
                  unsigned max_chain=0;
                  unsigned tmp;
                  unsigned long total=0;

                  for(entry_hash *h = FE->active; h!=NULL; h = h->next_active) {
                        if(!(e=h->root)) continue;
                        used++;
                        tmp=0;
                        for(;e!=NULL;e=e->next) {
                              tmp++;
                        }
                        total+=tmp;
                        if(max_chain<tmp) max_chain=tmp;
                  }

                  cli_print(cli, "    HASH: size=%u, %lu flows hashed, %u nodes used, max chain= %u",
                        FLOW_HASH_SIZE,total,used,max_chain);
#ifdef HAVE_BW                
                  BWEngine *bw = FE->BW;
                  if(bw) {
                        BWdata *b;
                        BWdata **table=bw->table;
                        unsigned used=0;
                        unsigned max_chain=0;
                        unsigned tmp;
                        unsigned long total=0;

                        for(unsigned i=0;i<BW_HASH_SIZE;i++) {
                              if(!(b=table[i])) continue;
                              used++;
                              tmp=0;
                              for(;b!=NULL;b=b->next) {
                                    tmp++;
                              }
                              total+=tmp;
                              if(max_chain<tmp) max_chain=tmp;
                        }

                        cli_print(cli, "    BW HASH: size=%u, %lu bws hashed , %u nodes used, max chain= %u",
                              BW_HASH_SIZE, total, used, max_chain);
                              
                        cli_print(cli, "    BW HASH: %u/%u slots/ready, %u/%u wrappers/ready, %u bytes",
                              bw->bwd_used, bw->bwd_total-bw->bwd_used,
                              bw->bwu_used, bw->bwu_total-bw->bwu_used,
                              bw->bwd_total*sizeof(BWdata)+bw->bwu_total*sizeof(bwUlist)
                        );
                  }
#endif
            }
            
            //show fifo
            DS_FIFO *fifo=ds->ds_fifo;
            unsigned msg_size=sizeof(EngineMsg)+sizeof(struct attribute)*ds->max_flow_slots;
            if(fifo) 
                  cli_print(cli, "    FIFO: %u/%u used/ready messages, each %u, total %u bytes",
                        fifo->num_items,fifo->ready_items, msg_size,
                        (fifo->num_items+fifo->ready_items)*msg_size);
            
            //show sources info
            if(ds->pt_type==PT_NETFLOW_TRAFFIC) {
                  char buf[32];
                  in_addr ina;
                  cli_print(cli, "    Total: %llu packets, %llu flows, %u errors, timestamp - %s",
                        ds->total_packets, ds->total_flows, ds->total_errors,
                        (ds->timestamp)?timeU2T((time_t)ds->timestamp, buf):"never");
                  for(NFSource *nf=ds->nfroot; nf!=NULL; nf=nf->next) {
                        ina.s_addr=nf->src_addr;
                        cli_print(cli, "    Source %s: %llu packets, %llu flows, %u errors, timestamp - %s",
                              inet_ntop(AF_INET, &ina, buffer, 32), nf->packets, nf->flows, nf->errors,
                              (nf->timestamp)?timeU2T((time_t)nf->timestamp, buf):"never");
                  }
#ifndef NOPCAP
            } else if (ds->pt_type==PT_LIBPCAP_TRAFFIC) {
                  ds_libpcap_stats(cli, ds);
#endif
#ifdef FREEBSD
#ifndef MACOS
            } else if (ds->pt_type==PT_NETGRAPH) {
                  ds_netgraph_stats(cli, ds);
#endif
#endif
            }
      }
      return CLI_OK;
}
//////////////////////////////////////////////////////////////////////////
void Service_DS::AcctFlows() {
      
      while((msg=ds_fifo->Pop(msg))) {
            IPtree->ACCT(msg->flow);
#ifdef LAYER7_FILTER
            layer7_freeinfo(msg->flow);
#endif
      }
}
//////////////////////////////////////////////////////////////////////////
unsigned Service_DS::Measure(struct timeval *start, unsigned len) {
      unsigned diff;
      struct timeval stop;

      netams_gettimeofday(&stop, NULL);
      
      diff= (unsigned) ( (stop.tv_sec - start->tv_sec)*1000000 + (stop.tv_usec - start->tv_usec));
      
      total_packets++;
      delay += diff;
      skewdelay = (unsigned)(skewdelay * 98 + diff * 2)/100;
      
      if(start->tv_sec - tc > LOAD_INTERVAL) {
            ptc = tc;   tc    = start->tv_sec;
            ppc = pc;   pc    = 0;
            pbc = bc;   bc = 0;
      }

      pc++;
      bc += len;

      aDebug(DEBUG_DS_IP, "ds:%u packet processed in %u mcsec\n",instance, diff);

      return diff;
}
//////////////////////////////////////////////////////////////////////////
void Service_DS::ShowInfo(struct cli_def *cli) {
      unsigned avg_pps;
      u_long avg_bps;

      if(tc - ptc <= 2*LOAD_INTERVAL) {
            avg_pps = ppc/(LOAD_INTERVAL);
            avg_bps = pbc/(LOAD_INTERVAL);
      } else {
            avg_pps = 0;
            avg_bps = 0;
      }
      
      const char *pt;
                
      switch (pt_type){
            case PT_IP_TRAFFIC: pt="IP_FILT"; break;
            case PT_NETFLOW_TRAFFIC: pt="NETFLOW"; break;
            case PT_LIBPCAP_TRAFFIC: pt="LIBPCAP"; break;
            case PT_NETGRAPH: pt="NETGRAPH"; break;
            case PT_RAW: pt="RAW"; break;
            default : pt="<\?\?>"; break;
      }

      cli_print(cli, " Data-source ID=%d type %s source %s:%u loop %llu average %d mcsec",
            instance, pt, src_cmd?src_cmd:"<>", port,
            total_packets, (total_packets)?(unsigned)(delay/total_packets):0
      );
                
      cli_print(cli, "    Perf: average skew delay %u mcsec, PPS: %u, BPS: %lu",
            skewdelay, avg_pps, avg_bps);
}
void Service_DS::ShowPerf(struct cli_def *cli, u_char isheader) {
      unsigned avg_pps;
      u_long avg_bps;

      if(tc - ptc < 2*LOAD_INTERVAL) {
            avg_pps = ppc/(LOAD_INTERVAL);
            avg_bps = pbc/(LOAD_INTERVAL);
      } else {
            avg_pps = 0;
            avg_bps = 0;
      }

      if (isheader)
            cli_bufprint(cli, "DsLOOP:%u DsAVG:%u DsDly:%u DsPps:%u DsBps:%u ",
                  instance, instance, instance, instance, instance);
      else
            cli_bufprint(cli, "%8llu %7u %7lu %7u %7lu\t",
                  total_packets,
                  (total_packets)?(unsigned)(delay/total_packets):0,
                  (u_long)skewdelay, avg_pps, avg_bps);
}
//////////////////////////////////////////////////////////////////////////
int Service_DS::unit2ds(unsigned addr, u_char mask, NetUnit *u, u_char flag) {
      if(IPtree) 
            IPtree->addr2tree(addr, mask, u, flag);
      return 1;
}
//////////////////////////////////////////////////////////////////////////

Generated by  Doxygen 1.6.0   Back to index