/* Extract a nice report from blackhole-control status It shows active connection rules with stats The rule are output order by usage (last used rule last) */ #include #include #include #include #include #include #include using namespace std; struct LINE { string last; int nbcon; string s1; string v1; string ip1; string port1; string s2; string v2; string port2; string source; LINE(const string &_last, int _nbcon, const string &_s1, const string &_v1, const string &_ip1, const string &_port1, const string &_s2, const string &_v2, const string &_port2, const string &_source){ last = _last; nbcon = _nbcon; s1 = _s1; v1 = _v1; ip1 = _ip1; port1 = _port1; s2 = _s2; v2 = _v2; port2 = _port2; source = _source; } bool operator < (const LINE &l) const { return last < l.last; } }; static void setmax (unsigned &maxv, const string &s) { if (s.size() > maxv) maxv = s.size(); } int main (int argc, char *argv[]) { glocal int ret = -1; glocal bool all = false; glocal bool noheader = false; glocal.ret = (argc,argv); setproginfo ("blackhole-stats",VERSION,"Prints connection statistics"); setarg ('a',"all","Prints all connection rules stats, including one with 0 activity",glocal.all,false); setarg ('n',"noheader","Only print the result, no header",glocal.noheader,false); glocal int ret = -1; glocal vector lines; ("blackhole-control status",10); enum columns {verb,s1,v1,ip1,port1,arrow,s2,v2,port2,nbcon,last,source}; vector tb; int n = str_splitline(line,' ',tb); if (n > 10 && (tb[verb] == "rule" || tb[verb] == "arule")){ const char *ptnbcon = tb[nbcon].c_str(); if (strncmp(ptnbcon,"nbcon=",6)==0) ptnbcon+=6; int nb = atoi(ptnbcon); if (nb > 0 || glocal.all){ const char *ptlast = tb[last].c_str(); if (strncmp(ptlast,"last=",5)==0) ptlast += 5; const char *pts = tb[source].c_str(); if (strncmp(pts,"last_source=",12)==0) pts += 12; glocal.lines.push_back(LINE(ptlast,nb,tb[s1],tb[v1],tb[ip1],tb[port1] ,tb[s2],tb[v2],tb[port2],pts)); } } glocal.ret = 0; return 0; sort (glocal.lines.begin(),glocal.lines.end()); // Compute the width of some columns; unsigned max_s1 = 0; unsigned max_v1 = 0; unsigned max_ip1 = 0; unsigned max_port1 = 0; unsigned max_s2 = 0; unsigned max_v2 = 0; unsigned max_port2 = 0; for (vector::iterator it=glocal.lines.begin(); it != glocal.lines.end(); it++){ setmax (max_s1,it->s1); setmax (max_v1,it->v1); setmax (max_ip1,it->ip1); setmax (max_port1,it->port1); setmax (max_s2,it->s2); setmax (max_v2,it->v2); setmax (max_port2,it->port2); } // vserver 1 may be very long since it may encode process path (findproc) if (max_v1 > 30) max_v1 = 30; if (!glocal.noheader){ unsigned col1 = max_s1+1+max_v1+1+max_ip1+1+max_port1; unsigned col2 = max_s2+1+max_v2+1+max_port2; printf ("%-19s %-6s %-*s | %-*s %s\n","last usage","nbcon",col1,"From",col2,"To","last-source"); printf ("%-19s %-6s ","-------------------","------"); for (unsigned i=0; i::iterator it=glocal.lines.begin(); it != glocal.lines.end(); it++){ printf ("%s %-6d %-*s %-*.*s %-*s %-*s | %-*s %-*s %-*s %s\n" ,it->last.c_str(),it->nbcon ,max_s1,it->s1.c_str(),max_v1,max_v1,it->v1.c_str(),max_ip1,it->ip1.c_str(),max_port1,it->port1.c_str() ,max_s2,it->s2.c_str(),max_v2,it->v2.c_str(),max_port2,it->port2.c_str() ,it->source.c_str()); } return glocal.ret; return glocal.ret; } /* blackhole-control status | while read verb s1 v1 ip1 port1 arrow s2 v2 port2 nbcon last source f g h i do if [ "$verb" = "rule" ]; then nbcon=`echo $nbcon | sed 's/=/ /' | (read a b; echo $b)` if [ "$nbcon" != 0 -o "$ALL" = on ] ; then last=`echo $last | sed 's/=/ /' | (read a b; echo $b)` source=`echo $source | sed 's/=/ /' | (read a b; echo $b)` port2=`echo $port2 | sed 's/://'` printf "%s %-6s %-20s %-30.30s %-10.10s %-5s | %-20s %-20.20s %-5s %s\n" $last $nbcon $s1 $v1 $ip1 $port1 $s2 $v2 $port2 $source fi fi done | sort */