Main Page | Class List | Directories | File List | Class Members | File Members

cfenvd.c

Go to the documentation of this file.
00001 /* 
00002 
00003         Copyright (C) 2001-
00004         Free Software Foundation, Inc.
00005 
00006    This file is part of GNU cfengine - written and maintained 
00007    by Mark Burgess, Dept of Computing and Engineering, Oslo College,
00008    Dept. of Theoretical physics, University of Oslo
00009  
00010    This program is free software; you can redistribute it and/or modify it
00011    under the terms of the GNU General Public License as published by the
00012    Free Software Foundation; either version 2, or (at your option) any
00013    later version. 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018  
00019   You should have received a copy of the GNU General Public License
00020   along with this program; if not, write to the Free Software
00021   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
00022 
00023 */
00024 
00025 /*****************************************************************************/
00026 /*                                                                           */
00027 /* File: cfenvd.c                                                            */
00028 /*                                                                           */
00029 /* Description: Long term state registry                                     */
00030 /*                                                                           */
00031 /* Based on the results of the ECG project, by Mark, Sigmund Straumsnes      */
00032 /* and Hårek Haugerud, Oslo University College 1998                          */
00033 /*                                                                           */
00034 /*****************************************************************************/
00035 
00036 #include "../pub/getopt.h"
00037 #include "cf.defs.h"
00038 #include "cf.extern.h"
00039 #ifdef HAVE_SYS_LOADAVG_H
00040 # include <sys/loadavg.h>
00041 #else
00042 # define LOADAVG_5MIN    1
00043 #endif
00044 #include <math.h>
00045 #include <db.h>
00046 
00047 /*****************************************************************************/
00048 /* Globals                                                                   */
00049 /*****************************************************************************/
00050 
00051 #define CFGRACEPERIOD 4.0   /* training period in units of counters (weeks,iterations)*/
00052 
00053 unsigned int HISTOGRAM[ATTR*2+5+PH_LIMIT][7][GRAINS];
00054 
00055 int HISTO = false;
00056 int NUMBER_OF_USERS;
00057 int ROOTPROCS;
00058 int OTHERPROCS;
00059 int DISKFREE;
00060 int LOADAVG;
00061 int INCOMING[ATTR];
00062 int OUTGOING[ATTR];
00063 int PH_SAMP[PH_LIMIT];
00064 int PH_LAST[PH_LIMIT];
00065 int PH_DELTA[PH_LIMIT];
00066 int SLEEPTIME = 5 * 60;
00067 int BATCH_MODE = false;
00068 double ITER = 0.0;        /* Iteration since start */
00069 double AGE,WAGE;          /* Age and weekly age of database */
00070 
00071 char OUTPUT[bufsize*2];
00072 
00073 char BATCHFILE[bufsize];
00074 char STATELOG[bufsize];
00075 char ENV_NEW[bufsize];
00076 char ENV[bufsize];
00077 
00078 struct Averages LOCALAV;
00079 struct Item *ALL_INCOMING = NULL;
00080 struct Item *ALL_OUTGOING = NULL;
00081 
00082 double ENTROPY = 0.0;
00083 double LAST_HOUR_ENTROPY = 0.0;
00084 double LAST_DAY_ENTROPY = 0.0;
00085 
00086 struct Item *PREVIOUS_STATE = NULL;
00087 
00088 struct option CFDENVOPTIONS[] =
00089    {
00090    {"help",no_argument,0,'h'},
00091    {"debug",optional_argument,0,'d'}, 
00092    {"verbose",no_argument,0,'v'},
00093    {"no-fork",no_argument,0,'F'},
00094    {"histograms",no_argument,0,'H'},
00095    {"file",optional_argument,0,'f'},
00096    {NULL,0,0,0}
00097    };
00098 
00099 short NO_FORK = false;
00100 
00101 /*****************************************************************************/
00102 
00103 enum socks
00104    {
00105    netbiosns,
00106    netbiosdgm,
00107    netbiosssn,
00108    irc,
00109    cfengine,
00110    nfsd,
00111    smtp,
00112    www,
00113    ftp,
00114    ssh,
00115    telnet
00116    };
00117 
00118 char *ECGSOCKS[ATTR][2] =
00119    {
00120    {"137","netbiosns"},
00121    {"138","netbiosdgm"},
00122    {"139","netbiosssn"},
00123    {"194","irc"},
00124    {"5308","cfengine"},
00125    {"2049","nfsd"},
00126    {"25","smtp"},
00127    {"80","www"},
00128    {"21","ftp"},
00129    {"22","ssh"},
00130    {"23","telnet"},
00131    };
00132 
00133 char *PH_BINARIES[PH_LIMIT] =   /* Miss leading slash */
00134    {
00135    "usr/sbin/atd",
00136    "sbin/getty",
00137    "bin/bash",
00138    "usr/sbin/exim",
00139    "bin/run-parts",
00140    };
00141 
00142 /*******************************************************************/
00143 /* Prototypes                                                      */
00144 /*******************************************************************/
00145 
00146 void CheckOptsAndInit ARGLIST((int argc,char **argv));
00147 void Syntax ARGLIST((void));
00148 void StartServer ARGLIST((int argc, char **argv));
00149 void DoBatch ARGLIST((void));
00150 void *ExitCleanly ARGLIST((void));
00151 void yyerror ARGLIST((char *s));
00152 void FatalError ARGLIST((char *s));
00153 void RotateFiles ARGLIST((char *s, int n));
00154 
00155 void GetDatabaseAge ARGLIST((void));
00156 void LoadHistogram  ARGLIST((void));
00157 void GetQ ARGLIST((void));
00158 char *GetTimeKey ARGLIST((void));
00159 struct Averages EvalAvQ ARGLIST((char *timekey));
00160 void ArmClasses ARGLIST((struct Averages newvals,char *timekey));
00161 
00162 void GatherProcessData ARGLIST((void));
00163 void GatherDiskData ARGLIST((void));
00164 void GatherLoadData ARGLIST((void));
00165 void GatherSocketData ARGLIST((void));
00166 void GatherPhData ARGLIST((void));
00167 struct Averages *GetCurrentAverages ARGLIST((char *timekey));
00168 void UpdateAverages ARGLIST((char *timekey, struct Averages newvals));
00169 void UpdateDistributions ARGLIST((char *timekey, struct Averages *av));
00170 double WAverage ARGLIST((double newvals,double oldvals, double age));
00171 void SetClasses ARGLIST((double expect,double delta,double sigma,double lexpect,double ldelta,double lsigma,char *name,struct Item **list,char *timekey));
00172 void SetVariable ARGLIST((char *name,double now, double average, double stddev, struct Item **list));
00173 void RecordChangeOfState  ARGLIST((struct Item *list,char *timekey));
00174 double RejectAnomaly ARGLIST((double new,double av,double var,double av2,double var2));
00175 int HashPhKey ARGLIST((char *s));
00176 
00177 /*******************************************************************/
00178 /* Level 0 : Main                                                  */
00179 /*******************************************************************/
00180 
00181 int main (argc,argv)
00182 
00183 int argc;
00184 char **argv;
00185 
00186 {
00187 CheckOptsAndInit(argc,argv);
00188 GetNameInfo();
00189 
00190 if (BATCH_MODE)
00191    {
00192    DoBatch();
00193    }
00194 else
00195    {
00196    StartServer(argc,argv);
00197    }
00198 
00199 return 0;
00200 }
00201 
00202 /********************************************************************/
00203 /* Level 1                                                          */
00204 /********************************************************************/
00205 
00206 void CheckOptsAndInit(argc,argv)
00207 
00208 int argc;
00209 char **argv;
00210 
00211 { extern char *optarg;
00212  int optindex = 0;
00213  int c, i,j,k;
00214 
00215 umask(077);
00216 sprintf(VPREFIX,"cfenvd"); 
00217 openlog(VPREFIX,LOG_PID|LOG_NOWAIT|LOG_ODELAY,LOG_DAEMON);
00218 
00219 strcpy(CFLOCK,"cfenvd");
00220  
00221 IGNORELOCK = false; 
00222 OUTPUT[0] = '\0';
00223 
00224 while ((c=getopt_long(argc,argv,"d:f:vhHFV",CFDENVOPTIONS,&optindex)) != EOF)
00225   {
00226   switch ((char) c)
00227       {
00228       case 'd': 
00229 
00230                 switch ((optarg==NULL)?3:*optarg)
00231                    {
00232                    case '1': D1 = true;
00233                              break;
00234                    case '2': D2 = true;
00235                              break;
00236                    default:  DEBUG = true;
00237                              break;
00238                    }
00239                 
00240                 NO_FORK = true;
00241                 printf("cfenvd: Debug mode: running in foreground\n");
00242                 break;
00243 
00244       case 'f': /* This is for us Oslo folks to test against old data in batch */
00245 
00246                 strcpy(BATCHFILE,optarg);
00247                 NO_FORK = true;
00248                 BATCH_MODE = true;
00249                 printf("Working in batch mode on file %s\n",BATCHFILE);
00250                 break;
00251 
00252       case 'v': VERBOSE = true;
00253                 break;
00254 
00255       case 'V': printf("GNU %s-%s daemon\n%s\n",PACKAGE,VERSION,COPYRIGHT);
00256                 printf("This program is covered by the GNU Public License and may be\n");
00257                 printf("copied free of charge. No warrenty is implied.\n\n");
00258                 exit(0);
00259                 break;
00260 
00261       case 'F': NO_FORK = true;
00262                 break;
00263 
00264       case 'H': HISTO = true;
00265                 break;
00266                 
00267       default:  Syntax();
00268                 exit(1);
00269 
00270       }
00271    }
00272 
00273 LOGGING = true;                    /* Do output to syslog */
00274  
00275 sprintf(VBUFF,"%s/test",WORKDIR);
00276 MakeDirectoriesFor(VBUFF,'y');
00277 sprintf(VBUFF,"%s/state/test",WORKDIR);
00278 MakeDirectoriesFor(VBUFF,'y');
00279 strncpy(VLOCKDIR,WORKDIR,bufsize-1);
00280 strncpy(VLOGDIR,WORKDIR,bufsize-1);
00281 
00282 for (i = 0; i < ATTR; i++)
00283    {
00284    sprintf(VBUFF,"%s/state/cf_incoming.%s",WORKDIR,ECGSOCKS[i][1]);
00285    CreateEmptyFile(VBUFF);
00286    sprintf(VBUFF,"%s/state/cf_outgoing.%s",WORKDIR,ECGSOCKS[i][1]);
00287    CreateEmptyFile(VBUFF);
00288    }
00289 
00290 sprintf(VBUFF,"%s/state/cf_users",WORKDIR);
00291 CreateEmptyFile(VBUFF);
00292  
00293 snprintf(AVDB,bufsize,"%s/state/%s",WORKDIR,AVDB_FILE);
00294 snprintf(STATELOG,bufsize,"%s/state/%s",WORKDIR,STATELOG_FILE);
00295 snprintf(ENV_NEW,bufsize,"%s/state/%s",WORKDIR,ENV_NEW_FILE);
00296 snprintf(ENV,bufsize,"%s/state/%s",WORKDIR,ENV_FILE);
00297 
00298 if (!BATCH_MODE)
00299    {
00300    GetDatabaseAge();
00301    LOCALAV.expect_number_of_users = 0.0; 
00302    LOCALAV.expect_rootprocs = 0.0;
00303    LOCALAV.expect_otherprocs = 0.0;
00304    LOCALAV.expect_diskfree = 0.0;
00305    LOCALAV.expect_loadavg = 0.0;
00306    LOCALAV.var_number_of_users = 0.0; 
00307    LOCALAV.var_rootprocs = 0.0;
00308    LOCALAV.var_otherprocs = 0.0;
00309    LOCALAV.var_diskfree = 0.0;
00310    LOCALAV.var_loadavg = 0.0;
00311 
00312    for (i = 0; i < ATTR; i++)
00313       {
00314       LOCALAV.expect_incoming[i] = 0.0;
00315       LOCALAV.expect_outgoing[i] = 0.0;
00316       LOCALAV.var_incoming[i] = 0.0;
00317       LOCALAV.var_outgoing[i] = 0.0;
00318       }
00319 
00320    for (i = 0; i < PH_LIMIT; i++)
00321       {
00322       LOCALAV.expect_pH[i] = 0.0;
00323       LOCALAV.var_pH[i] = 0.0;
00324       }
00325 
00326    }
00327 
00328 for (i = 0; i < 7; i++)
00329    {
00330    for (j = 0; j < ATTR*2+5+PH_LIMIT; j++)
00331       {
00332       for (k = 0; k < GRAINS; k++)
00333           {
00334           HISTOGRAM[i][j][k] = 0;
00335           }
00336       }
00337    }
00338 
00339 for (i = 0; i < PH_LIMIT; i++)
00340    {
00341    PH_SAMP[i] = PH_LAST[i] = 0.0;
00342    }
00343  
00344 srand((unsigned int)time(NULL)); 
00345 LoadHistogram(); 
00346 }
00347 
00348 /*********************************************************************/
00349 /* Level 2                                                           */
00350 /*********************************************************************/
00351 
00352 void Syntax()
00353 
00354 { int i;
00355 
00356 printf("GNU cfengine environment daemon\n%s-%s\n%s\n",PACKAGE,VERSION,COPYRIGHT);
00357 printf("\n");
00358 printf("Options:\n\n");
00359 
00360 for (i=0; CFDENVOPTIONS[i].name != NULL; i++)
00361    {
00362    printf("--%-20s    (-%c)\n",CFDENVOPTIONS[i].name,(char)CFDENVOPTIONS[i].val);
00363    }
00364 
00365 printf("\nBug reports to bug-cfengine@gnu.org (News: gnu.cfengine.bug)\n");
00366 printf("General help to help-cfengine@gnu.org (News: gnu.cfengine.help)\n");
00367 printf("Info & fixes at http://www.iu.hio.no/cfengine\n");
00368 }
00369 
00370 /*********************************************************************/
00371 
00372 void GetDatabaseAge()
00373 
00374 { int errno;
00375   DBT key,value;
00376   DB *dbp;
00377 
00378 if ((errno = db_create(&dbp,NULL,0)) != 0)
00379    {
00380    snprintf(OUTPUT,bufsize,"Couldn't open average database %s\n",AVDB);
00381    CfLog(cferror,OUTPUT,"db_open");
00382    return;
00383    }
00384 
00385 #ifdef CF_OLD_DB
00386 if ((errno = dbp->open(dbp,AVDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0)
00387 #else
00388 if ((errno = dbp->open(dbp,NULL,AVDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0)    
00389 #endif
00390    {
00391    snprintf(OUTPUT,bufsize,"Couldn't open average database %s\n",AVDB);
00392    CfLog(cferror,OUTPUT,"db_open");
00393    return;
00394    }
00395 
00396 chmod(AVDB,0644); 
00397 
00398 bzero(&key,sizeof(key));       
00399 bzero(&value,sizeof(value));
00400       
00401 key.data = "DATABASE_AGE";
00402 key.size = strlen("DATABASE_AGE")+1;
00403 
00404 if ((errno = dbp->get(dbp,NULL,&key,&value,0)) != 0)
00405    {
00406    if (errno != DB_NOTFOUND)
00407       {
00408       dbp->err(dbp,errno,NULL);
00409       dbp->close(dbp,0);
00410       return;
00411       }
00412    }
00413  
00414 dbp->close(dbp,0);
00415 
00416 if (value.data != NULL)
00417    {
00418    AGE = *(double *)(value.data);
00419    WAGE = AGE / CFWEEK * MEASURE_INTERVAL;
00420    Debug("\n\nPrevious DATABASE_AGE %f\n\n",AGE);
00421    }
00422 else
00423    {
00424    Debug("No previous AGE\n");
00425    AGE = 0.0;
00426    }
00427 }
00428 
00429 /*********************************************************************/
00430 
00431 void LoadHistogram()
00432 
00433 { FILE *fp;
00434   int position,i,day; 
00435 
00436 if (HISTO)
00437    {
00438    char filename[bufsize];
00439    
00440    snprintf(filename,bufsize,"%s/state/histograms",WORKDIR);
00441    
00442    if ((fp = fopen(filename,"r")) == NULL)
00443       {
00444       CfLog(cfverbose,"Unable to load histogram data","fopen");
00445       return;
00446       }
00447 
00448    for (position = 0; position < GRAINS; position++)
00449       {
00450       fscanf(fp,"%d ",&position);
00451       
00452       for (i = 0; i < 5 + 2*ATTR+PH_LIMIT; i++)
00453          {
00454          for (day = 0; day < 7; day++)
00455             {
00456             fscanf(fp,"%d ",&(HISTOGRAM[i][day][position]));
00457             }
00458          }
00459       }
00460    
00461    fclose(fp);
00462    }
00463 } 
00464 
00465 /*********************************************************************/
00466 
00467 void DoBatch()
00468 
00469 { FILE *fp;
00470   char buffer[4096],time[256],timekey[256];
00471   float v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v15,v16,v17,v18,v19,v20,v21,v22,v23,v24,v25,v26;
00472   DB *dbp;
00473   int i = 0;
00474 
00475 sprintf(AVDB,"/tmp/cfenv.tmp.db");
00476 unlink(AVDB);
00477  
00478 if ((errno = db_create(&dbp,NULL,0)) != 0)
00479    {
00480    sprintf(OUTPUT,"Couldn't open average database %s\n",AVDB);
00481    CfLog(cferror,OUTPUT,"db_open");
00482    return;
00483    }
00484 
00485 #ifdef CF_OLD_DB
00486 if ((errno = dbp->open(dbp,AVDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0)
00487 #else
00488 if ((errno = dbp->open(dbp,NULL,AVDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0)    
00489 #endif
00490    {
00491    sprintf(OUTPUT,"Couldn't open average database %s\n",AVDB);
00492    CfLog(cferror,OUTPUT,"db_open");
00493    return;
00494    }
00495   
00496 if ((fp=fopen(BATCHFILE,"r")) == NULL)
00497    {
00498    printf("Cannot open %s\n",BATCHFILE);
00499    return;
00500    }
00501 
00502 while (!feof(fp))
00503    {
00504    bzero(buffer,4096);
00505    fgets(buffer,1024,fp);
00506    if (i++ % 1024 == 0)
00507       {
00508       printf("   * Working %d ... *\r",i);
00509       }
00510    
00511    sscanf(buffer,"%[^,],%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f",time,&v1,&v2,&v3,&v4,&v5,&v6,&v7,&v8,&v9,&v10,&v11,&v12,&v13,&v14,&v15,&v16,&v17,&v18,&v19,&v20,&v21,&v22,&v23,&v24,&v25,&v26);
00512 
00513    Debug("%s,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f",time,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v15,v16,v17,v18,v19,v20,v21,v22,v23,v24,v25,v26);
00514 
00515    NUMBER_OF_USERS = (double)v1;
00516    ROOTPROCS = (double)v4;
00517    OTHERPROCS = (double)v5;
00518    DISKFREE = (double)v6;
00519    INCOMING[cfengine] = (double)v13;
00520    OUTGOING[cfengine] = (double)v14;
00521    INCOMING[nfsd] = (double)v15;
00522    OUTGOING[nfsd] = (double)v16;
00523    INCOMING[smtp] = (double)v17;
00524    OUTGOING[smtp] = (double)v18;
00525    INCOMING[www] = (double)v19;
00526    OUTGOING[www] = (double)v20;
00527    INCOMING[ftp] = (double)v21;
00528    OUTGOING[ftp] = (double)v22;
00529    INCOMING[ssh] = (double)v23;
00530    OUTGOING[ssh] = (double)v24;
00531    INCOMING[telnet] = (double)v25;
00532    OUTGOING[telnet] = (double)v26;
00533 
00534    strcpy(timekey,ConvTimeKey(time));
00535 
00536    (void)EvalAvQ(timekey);
00537    }
00538 
00539 fclose(fp);
00540 dbp->close(dbp,0);
00541 printf("\nDone - database saved to %s\n",AVDB);
00542 printf("Run cfenvgraph -f %s to generate graphs\n\n",AVDB); 
00543 }
00544 
00545 /*********************************************************************/
00546 
00547 void StartServer(argc,argv)
00548 
00549 int argc;
00550 char **argv;
00551 
00552 { char *timekey;
00553   struct Averages averages;
00554   void HandleSignal();
00555 
00556 if ((!NO_FORK) && (fork() != 0))
00557    {
00558    sprintf(OUTPUT,"cfenvd: starting\n");
00559    CfLog(cfinform,OUTPUT,"");
00560    exit(0);
00561    }
00562 
00563 if (!NO_FORK)
00564    {
00565    ActAsDaemon(0);
00566    }
00567 
00568 signal (SIGTERM,HandleSignal);                   /* Signal Handler */
00569 signal (SIGHUP,HandleSignal);
00570 signal (SIGINT,HandleSignal);
00571 signal (SIGPIPE,HandleSignal);
00572 signal (SIGSEGV,HandleSignal);
00573 
00574 VCANONICALFILE = strdup("db");
00575  
00576 if (!GetLock("cfenvd","daemon",0,1,"localhost",(time_t)time(NULL)))
00577    {
00578    return;
00579    }
00580     
00581 while (true)
00582    {
00583    GetQ();
00584    timekey = GetTimeKey();
00585    averages = EvalAvQ(timekey);
00586    ArmClasses(averages,timekey);
00587    sleep(SLEEPTIME);
00588    ITER++;
00589    }
00590 }
00591 
00592 /*********************************************************************/
00593 
00594 void yyerror(s)
00595 
00596 char *s;
00597 
00598 {
00599  /* Dummy */
00600 }
00601 
00602 /*********************************************************************/
00603 
00604 void RotateFiles(name,number)
00605 
00606 char *name;
00607 int number;
00608 
00609 {
00610  /* Dummy */
00611 }
00612 
00613 /*********************************************************************/
00614 
00615 void FatalError(s)
00616 
00617 char *s;
00618 
00619 {
00620 fprintf (stderr,"%s:%s:%s\n",VPREFIX,VCURRENTFILE,s);
00621 closelog(); 
00622 exit(1);
00623 }
00624 
00625 /*********************************************************************/
00626 /* Level 2                                                           */
00627 /*********************************************************************/
00628 
00629 void GetQ()
00630 
00631 {
00632 Debug("========================= GET Q ==============================\n");
00633 GatherProcessData();
00634 GatherLoadData(); 
00635 GatherDiskData();
00636 GatherSocketData();
00637 GatherPhData(); 
00638 }
00639 
00640 
00641 /*********************************************************************/
00642 
00643 char *GetTimeKey()
00644 
00645 { time_t now;
00646   char str[64];
00647   
00648 if ((now = time((time_t *)NULL)) == -1)
00649    {
00650    exit(1);
00651    }
00652 
00653 sprintf(str,"%s",ctime(&now));
00654 
00655 return ConvTimeKey(str); 
00656 }
00657 
00658 
00659 /*********************************************************************/
00660 
00661 struct Averages EvalAvQ(t)
00662 
00663 char *t;
00664 
00665 { struct Averages *currentvals,newvals;
00666   int i; 
00667   double Number_Of_Users,Rootprocs,Otherprocs,Diskfree,LoadAvg;
00668   double Incoming[ATTR],Outgoing[ATTR],pH_delta[PH_LIMIT];
00669 
00670 if ((currentvals = GetCurrentAverages(t)) == NULL)
00671    {
00672    CfLog(cferror,"Error reading average database","");
00673    exit(1);
00674    }
00675 
00676 /* Discard any apparently anomalous behaviour before renormalizing database */
00677 
00678 Number_Of_Users = RejectAnomaly(NUMBER_OF_USERS,
00679                                 currentvals->expect_number_of_users,
00680                                 currentvals->var_number_of_users,
00681                                 LOCALAV.expect_number_of_users,
00682                                 LOCALAV.var_number_of_users);
00683 Rootprocs = RejectAnomaly(ROOTPROCS,
00684                           currentvals->expect_rootprocs,
00685                           currentvals->var_rootprocs,
00686                           LOCALAV.expect_rootprocs,
00687                           LOCALAV.var_rootprocs);
00688 
00689 Otherprocs = RejectAnomaly(OTHERPROCS,
00690                            currentvals->expect_otherprocs,
00691                            currentvals->var_otherprocs,
00692                            LOCALAV.expect_otherprocs,
00693                            LOCALAV.var_otherprocs);
00694 
00695 Diskfree = RejectAnomaly(DISKFREE,
00696                          currentvals->expect_diskfree,
00697                          currentvals->var_diskfree, 
00698                          LOCALAV.expect_diskfree,
00699                          LOCALAV.var_diskfree);
00700 
00701 LoadAvg = RejectAnomaly(LOADAVG,
00702                          currentvals->expect_loadavg,
00703                          currentvals->var_loadavg, 
00704                          LOCALAV.expect_loadavg,
00705                          LOCALAV.var_loadavg);
00706 
00707  
00708 for (i = 0; i < ATTR; i++)
00709    {
00710    Incoming[i] = RejectAnomaly(INCOMING[i],
00711                                currentvals->expect_incoming[i],
00712                                currentvals->var_incoming[i],
00713                                LOCALAV.expect_incoming[i],
00714                                LOCALAV.var_incoming[i]);
00715 
00716    Outgoing[i] = RejectAnomaly(OUTGOING[i],
00717                                currentvals->expect_outgoing[i],
00718                                currentvals->var_outgoing[i],
00719                                LOCALAV.expect_outgoing[i],
00720                                LOCALAV.var_outgoing[i]);
00721    }
00722 
00723 
00724 for (i = 0; i < PH_LIMIT; i++)
00725    {
00726    pH_delta[i] = RejectAnomaly(PH_DELTA[i],
00727                                currentvals->expect_pH[i],
00728                                currentvals->var_pH[i],
00729                                LOCALAV.expect_pH[i],
00730                                LOCALAV.var_pH[i]);
00731    }
00732  
00733 newvals.expect_number_of_users = WAverage(Number_Of_Users,currentvals->expect_number_of_users,WAGE);
00734 newvals.expect_rootprocs = WAverage(Rootprocs,currentvals->expect_rootprocs,WAGE);
00735 newvals.expect_otherprocs = WAverage(Otherprocs,currentvals->expect_otherprocs,WAGE);
00736 newvals.expect_diskfree = WAverage(Diskfree,currentvals->expect_diskfree,WAGE);
00737 newvals.expect_loadavg = WAverage(LoadAvg,currentvals->expect_loadavg,WAGE); 
00738 
00739 LOCALAV.expect_number_of_users = WAverage(newvals.expect_number_of_users,LOCALAV.expect_number_of_users,ITER); 
00740 LOCALAV.expect_rootprocs = WAverage(newvals.expect_rootprocs,LOCALAV.expect_rootprocs,ITER);
00741 LOCALAV.expect_otherprocs = WAverage(newvals.expect_otherprocs,LOCALAV.expect_otherprocs,ITER);
00742 LOCALAV.expect_diskfree = WAverage(newvals.expect_diskfree,LOCALAV.expect_diskfree,ITER);
00743 LOCALAV.expect_loadavg = WAverage(newvals.expect_loadavg,LOCALAV.expect_loadavg,ITER); 
00744  
00745 newvals.var_number_of_users = WAverage((Number_Of_Users-newvals.expect_number_of_users)*(Number_Of_Users-newvals.expect_number_of_users),currentvals->var_number_of_users,WAGE);
00746 newvals.var_rootprocs = WAverage((Rootprocs-newvals.expect_rootprocs)*(Rootprocs-newvals.expect_rootprocs),currentvals->var_rootprocs,WAGE);
00747 newvals.var_otherprocs = WAverage((Otherprocs-newvals.expect_otherprocs)*(Otherprocs-newvals.expect_otherprocs),currentvals->var_otherprocs,WAGE);
00748 newvals.var_diskfree = WAverage((Diskfree-newvals.expect_diskfree)*(Diskfree-newvals.expect_diskfree),currentvals->var_diskfree,WAGE);
00749 newvals.var_loadavg = WAverage((LoadAvg-newvals.expect_loadavg)*(LoadAvg-newvals.expect_loadavg),currentvals->var_loadavg,WAGE); 
00750 
00751 LOCALAV.var_number_of_users = WAverage((Number_Of_Users-LOCALAV.expect_number_of_users)*(Number_Of_Users-LOCALAV.expect_number_of_users),LOCALAV.var_number_of_users,ITER);
00752 LOCALAV.var_rootprocs = WAverage((Rootprocs-LOCALAV.expect_rootprocs)*(Rootprocs-LOCALAV.expect_rootprocs),LOCALAV.var_rootprocs,ITER);
00753 LOCALAV.var_otherprocs = WAverage((Otherprocs-LOCALAV.expect_otherprocs)*(Otherprocs-LOCALAV.expect_otherprocs),LOCALAV.var_otherprocs,ITER);
00754 LOCALAV.var_diskfree = WAverage((Diskfree-LOCALAV.expect_diskfree)*(Diskfree-LOCALAV.expect_diskfree),LOCALAV.var_diskfree,ITER);
00755 LOCALAV.var_loadavg = WAverage((LoadAvg-LOCALAV.expect_loadavg)*(LoadAvg-LOCALAV.expect_loadavg),currentvals->var_loadavg,WAGE); 
00756  
00757 Verbose("Users              = %4d -> (%f#%f) local [%f#%f]\n",NUMBER_OF_USERS,newvals.expect_number_of_users,sqrt(newvals.var_number_of_users),LOCALAV.expect_number_of_users,sqrt(LOCALAV.var_number_of_users));
00758 Verbose("Rootproc           = %4d -> (%f#%f) local [%f#%f]\n",ROOTPROCS,newvals.expect_rootprocs,sqrt(newvals.var_rootprocs),LOCALAV.expect_rootprocs,sqrt(LOCALAV.var_rootprocs));
00759 Verbose("Otherproc          = %4d -> (%f#%f) local [%f#%f]\n",OTHERPROCS,newvals.expect_otherprocs,sqrt(newvals.var_otherprocs),LOCALAV.expect_otherprocs,sqrt(LOCALAV.var_otherprocs));
00760 Verbose("Diskpercent        = %4d -> (%f#%f) local [%f#%f]\n",DISKFREE,newvals.expect_diskfree,sqrt(newvals.var_diskfree),LOCALAV.expect_diskfree,sqrt(LOCALAV.var_diskfree));
00761 Verbose("Load Average       = %4d -> (%f#%f) local [%f#%f]\n",LOADAVG,newvals.expect_loadavg,sqrt(newvals.var_loadavg),LOCALAV.expect_loadavg,sqrt(LOCALAV.var_loadavg)); 
00762  
00763 for (i = 0; i < ATTR; i++)
00764    {
00765    newvals.expect_incoming[i] = WAverage(Incoming[i],currentvals->expect_incoming[i],WAGE);
00766    newvals.expect_outgoing[i] = WAverage(Outgoing[i],currentvals->expect_outgoing[i],WAGE);
00767    newvals.var_incoming[i] = WAverage((Incoming[i]-newvals.expect_incoming[i])*(Incoming[i]-newvals.expect_incoming[i]),currentvals->var_incoming[i],WAGE);
00768    newvals.var_outgoing[i] = WAverage((Outgoing[i]-newvals.expect_outgoing[i])*(Outgoing[i]-newvals.expect_outgoing[i]),currentvals->var_outgoing[i],WAGE);
00769 
00770    LOCALAV.expect_incoming[i] = WAverage(newvals.expect_incoming[i],LOCALAV.expect_incoming[i],ITER);
00771    LOCALAV.expect_outgoing[i] = WAverage(newvals.expect_outgoing[i],LOCALAV.expect_outgoing[i],ITER);
00772    LOCALAV.var_incoming[i] = WAverage((Incoming[i]-LOCALAV.expect_incoming[i])*(Incoming[i]-LOCALAV.expect_incoming[i]),LOCALAV.var_incoming[i],ITER);
00773 
00774    LOCALAV.var_outgoing[i] = WAverage((Outgoing[i]-LOCALAV.expect_outgoing[i])*(Outgoing[i]-LOCALAV.expect_outgoing[i]),LOCALAV.var_outgoing[i],ITER);
00775    
00776    Verbose("%-15s-in = %4d -> (%f#%f) local [%f#%f]\n",ECGSOCKS[i][1],INCOMING[i],newvals.expect_incoming[i],sqrt(newvals.var_incoming[i]),LOCALAV.expect_incoming[i],sqrt(LOCALAV.var_incoming[i]));
00777    Verbose("%-14s-out = %4d -> (%f#%f) local [%f#%f]\n",ECGSOCKS[i][1],OUTGOING[i],newvals.expect_outgoing[i],sqrt(newvals.var_outgoing[i]),LOCALAV.expect_outgoing[i],sqrt(LOCALAV.var_outgoing[i]));
00778    }
00779 
00780 
00781 for (i = 0; i < PH_LIMIT; i++)
00782    {
00783    if (PH_BINARIES[i] == NULL)
00784       {
00785       continue;
00786       }
00787    
00788    newvals.expect_pH[i] = WAverage(pH_delta[i],currentvals->expect_pH[i],WAGE);
00789    newvals.var_pH[i] = WAverage((pH_delta[i]-newvals.expect_pH[i])*(pH_delta[i]-newvals.expect_pH[i]),currentvals->var_pH[i],WAGE);
00790 
00791 
00792    LOCALAV.expect_pH[i] = WAverage(newvals.expect_pH[i],LOCALAV.expect_pH[i],ITER);
00793    LOCALAV.var_pH[i] = WAverage((pH_delta[i]-LOCALAV.expect_pH[i])*(pH_delta[i]-LOCALAV.expect_pH[i]),LOCALAV.var_pH[i],ITER);
00794 
00795    Verbose("%-15s-in = %4d -> (%f#%f) local [%f#%f]\n",CanonifyName(PH_BINARIES[i]),PH_DELTA[i],newvals.expect_pH[i],sqrt(newvals.var_pH[i]),LOCALAV.expect_pH[i],sqrt(LOCALAV.var_pH[i]));
00796 
00797    }
00798  
00799 UpdateAverages(t,newvals);
00800  
00801 if (WAGE > CFGRACEPERIOD)
00802    {
00803    UpdateDistributions(t,currentvals);  /* Distribution about mean */
00804    }
00805  
00806 return newvals;
00807 }
00808 
00809 /*********************************************************************/
00810 
00811 void ArmClasses(av,timekey)
00812 
00813 struct Averages av;
00814 char *timekey;
00815 
00816 { double sigma,delta,lsigma,ldelta;
00817   struct Item *classlist = NULL, *ip;
00818   int i;
00819   FILE *fp;
00820  
00821 delta = NUMBER_OF_USERS - av.expect_number_of_users;
00822 sigma = sqrt(av.var_number_of_users);
00823 ldelta = NUMBER_OF_USERS - LOCALAV.expect_number_of_users;
00824 lsigma = sqrt(LOCALAV.var_number_of_users);
00825  
00826 SetClasses(av.expect_number_of_users,delta,sigma,
00827            LOCALAV.expect_number_of_users,ldelta,lsigma,
00828            "Users",&classlist,timekey);
00829 
00830 SetVariable("users",NUMBER_OF_USERS,av.expect_number_of_users,lsigma,&classlist);
00831 
00832 delta = ROOTPROCS - av.expect_rootprocs;
00833 sigma = sqrt(av.var_rootprocs);
00834 ldelta = ROOTPROCS - LOCALAV.expect_rootprocs;
00835 lsigma = sqrt(LOCALAV.var_rootprocs);
00836 
00837 SetClasses(av.expect_rootprocs,delta,sigma,
00838            LOCALAV.expect_rootprocs,ldelta,lsigma,
00839            "RootProcs",&classlist,timekey);
00840 
00841 SetVariable("rootprocs",ROOTPROCS,av.expect_rootprocs,lsigma,&classlist);
00842 
00843 delta = OTHERPROCS - av.expect_otherprocs;
00844 sigma = sqrt(av.var_otherprocs);
00845 ldelta = OTHERPROCS - LOCALAV.expect_otherprocs;
00846 lsigma = sqrt(LOCALAV.var_otherprocs);
00847 
00848 SetClasses(av.expect_otherprocs,delta,sigma,
00849            LOCALAV.expect_otherprocs,ldelta,lsigma,
00850            "UserProcs",&classlist,timekey);
00851 
00852 
00853 SetVariable("userprocs",OTHERPROCS,av.expect_otherprocs,lsigma,&classlist);
00854 
00855 delta = DISKFREE - av.expect_diskfree;
00856 sigma = sqrt(av.var_diskfree);
00857 ldelta = DISKFREE - LOCALAV.expect_diskfree;
00858 lsigma = sqrt(LOCALAV.var_diskfree);
00859  
00860 SetClasses(av.expect_diskfree,delta,sigma,
00861            LOCALAV.expect_diskfree,ldelta,lsigma,
00862            "DiskFree",&classlist,timekey);
00863 
00864 SetVariable("diskfree",DISKFREE,av.expect_diskfree,lsigma,&classlist);
00865 
00866 SetClasses(av.expect_loadavg,delta,sigma,
00867            LOCALAV.expect_loadavg,ldelta,lsigma,
00868            "LoadAvg",&classlist,timekey);
00869 
00870 SetVariable("loadavg",LOADAVG,av.expect_loadavg,lsigma,&classlist);
00871  
00872 for (i = 0; i < ATTR; i++)
00873    {
00874    char name[256];
00875    strcpy(name,ECGSOCKS[i][1]);
00876    strcat(name,"_in");
00877    delta = INCOMING[i] - av.expect_incoming[i];
00878    sigma = sqrt(av.var_incoming[i]);
00879    ldelta = INCOMING[i] - LOCALAV.expect_incoming[i];
00880    lsigma = sqrt(LOCALAV.var_incoming[i]);
00881       
00882    SetClasses(av.expect_incoming[i],delta,sigma,
00883               LOCALAV.expect_incoming[i],ldelta,lsigma,
00884               name,&classlist,timekey);
00885 
00886    SetVariable(name,INCOMING[i],av.expect_incoming[i],lsigma,&classlist);
00887 
00888    strcpy(name,ECGSOCKS[i][1]);
00889    strcat(name,"_out");
00890    delta = OUTGOING[i] - av.expect_outgoing[i];
00891    sigma = sqrt(av.var_outgoing[i]);
00892    ldelta = OUTGOING[i] - LOCALAV.expect_outgoing[i];
00893    lsigma = sqrt(LOCALAV.var_outgoing[i]);
00894    
00895    SetClasses(av.expect_outgoing[i],delta,sigma,
00896               LOCALAV.expect_outgoing[i],ldelta,lsigma,
00897               name,&classlist,timekey);
00898 
00899    SetVariable(name,OUTGOING[i],av.expect_outgoing[i],lsigma,&classlist);
00900    }
00901 
00902 for (i = 0; i < PH_LIMIT; i++)
00903    {
00904    if (PH_BINARIES[i] == NULL)
00905       {
00906       continue;
00907       }
00908    
00909    delta = PH_DELTA[i] - av.expect_pH[i];
00910    sigma = sqrt(av.var_pH[i]);
00911    ldelta = PH_DELTA[i] - LOCALAV.expect_pH[i];
00912    lsigma = sqrt(LOCALAV.var_pH[i]);
00913       
00914    SetClasses(av.expect_pH[i],delta,sigma,
00915               LOCALAV.expect_pH[i],ldelta,lsigma,
00916               CanonifyName(PH_BINARIES[i]),&classlist,timekey);
00917 
00918    SetVariable(CanonifyName(PH_BINARIES[i]),PH_DELTA[i],av.expect_pH[i],lsigma,&classlist);
00919    }
00920 
00921  
00922 /*
00923 if (WAGE > CFGRACEPERIOD)
00924    {
00925    if (!OrderedListsMatch(PREVIOUS_STATE,classlist))
00926       {
00927       RecordChangeOfState(classlist,timekey);
00928       }
00929    }
00930 */
00931    
00932 unlink(ENV_NEW);
00933  
00934 if ((fp = fopen(ENV_NEW,"w")) == NULL)
00935    {
00936    DeleteItemList(PREVIOUS_STATE);
00937    PREVIOUS_STATE = classlist;
00938    return; 
00939    }
00940 
00941 for (ip = classlist; ip != NULL; ip=ip->next)
00942    {
00943    fprintf(fp,"%s\n",ip->name);
00944    }
00945  
00946 DeleteItemList(PREVIOUS_STATE);
00947 PREVIOUS_STATE = classlist; 
00948  
00949 for (ip = ALL_INCOMING; ip != NULL; ip=ip->next)
00950    { char *sp;
00951      int print=true;
00952    
00953    for (sp = ip->name; *sp != '\0'; sp++)
00954       {
00955       if (!isdigit((int)*sp))
00956          {
00957          print = false;
00958          }
00959       }
00960 
00961    if (print)
00962       {
00963       Debug("Port(in,%s) ",ip->name);
00964       fprintf(fp,"pin-%s\n",ip->name);
00965       }
00966    }
00967 
00968 Debug("\n\n"); 
00969 
00970 for (ip = ALL_OUTGOING; ip != NULL; ip=ip->next)
00971    { char *sp;
00972      int print=true;
00973      
00974    for (sp = ip->name; *sp != '\0'; sp++)
00975       {
00976       if (!isdigit((int)*sp))
00977          {
00978          continue;
00979          }
00980       }
00981 
00982    if (print)
00983       {
00984       Debug("Port(out,%s) ",ip->name);
00985       /* fprintf(fp,"pout-%s\n",ip->name);   */
00986       }
00987    }
00988 
00989 Debug("\n\n");  
00990 fclose(fp);
00991 
00992 rename(ENV_NEW,ENV);
00993 }
00994 
00995 /*********************************************************************/
00996 /* Level 3                                                           */
00997 /*********************************************************************/
00998 
00999 void GatherProcessData()
01000 
01001 { FILE *pp;
01002   char pscomm[bufsize];
01003   char user[maxvarsize];
01004   struct Item *list = NULL;
01005   
01006 snprintf(pscomm,bufsize,"%s %s",VPSCOMM[VSYSTEMHARDCLASS],VPSOPTS[VSYSTEMHARDCLASS]);
01007 
01008 NUMBER_OF_USERS = ROOTPROCS = OTHERPROCS = 0; 
01009 
01010 if ((pp = cfpopen(pscomm,"r")) == NULL)
01011    {
01012    return;
01013    }
01014 
01015 ReadLine(VBUFF,bufsize,pp); 
01016 
01017 while (!feof(pp))
01018    {
01019    ReadLine(VBUFF,bufsize,pp);
01020    sscanf(VBUFF,"%s",user);
01021    if (!IsItemIn(list,user))
01022       {
01023       PrependItem(&list,user,NULL);
01024       NUMBER_OF_USERS++;
01025       }
01026 
01027    if (strcmp(user,"root") == 0)
01028       {
01029       ROOTPROCS++;
01030       }
01031    else
01032       {
01033       OTHERPROCS++;
01034       }
01035 
01036    }
01037 
01038 cfpclose(pp);
01039 
01040 snprintf(VBUFF,maxvarsize,"%s/state/cf_users",WORKDIR);
01041 SaveItemList(list,VBUFF,"none");
01042  
01043 Verbose("(Users,root,other) = (%d,%d,%d)\n",NUMBER_OF_USERS,ROOTPROCS,OTHERPROCS);
01044 }
01045 
01046 /*****************************************************************************/
01047 
01048 void GatherDiskData()
01049 
01050 {
01051 DISKFREE = GetDiskUsage("/",cfpercent);
01052 Verbose("Disk free = %d %%\n",DISKFREE);
01053 }
01054 
01055 
01056 /*****************************************************************************/
01057 
01058 void GatherLoadData()
01059 
01060 { double load[4] = {0,0,0,0}, sum = 0.0; 
01061  int i,n = 1;
01062 
01063 Debug("GatherLoadData\n\n");
01064 
01065 #ifdef HAVE_GETLOADAVG 
01066 if ((n = getloadavg(load,LOADAVG_5MIN)) == -1)
01067    {
01068    LOADAVG = 0.0;
01069    }
01070 else
01071    {
01072    for (i = 0; i < n; i++)
01073       {
01074       Debug("Found load average to be %lf of %d samples\n", load[i],n);
01075       sum += load[i];
01076       }
01077    }
01078 #endif
01079 
01080 /* Scale load average by 100 to make it visible */
01081  
01082 LOADAVG = (int) (100.0 * sum);
01083 Verbose("100 x Load Average = %d\n",LOADAVG);
01084 }
01085 
01086 /*****************************************************************************/
01087 
01088 void GatherSocketData()
01089 
01090 { FILE *pp,*fpout;
01091   char local[bufsize],remote[bufsize],comm[bufsize];
01092   struct Item *in[ATTR],*out[ATTR];
01093   char *sp;
01094   int i;
01095   
01096 Debug("GatherSocketData()\n");
01097   
01098 for (i = 0; i < ATTR; i++)
01099    {
01100    INCOMING[i] = OUTGOING[i] = 0;
01101    in[i] = out[i] = NULL;
01102    }
01103 
01104 if (ALL_INCOMING != NULL)
01105    {
01106    DeleteItemList(ALL_INCOMING);
01107    ALL_INCOMING = NULL;
01108    }
01109 
01110 if (ALL_OUTGOING != NULL)
01111    {
01112    DeleteItemList(ALL_OUTGOING);
01113    ALL_OUTGOING = NULL;
01114    } 
01115  
01116 sscanf(VNETSTAT[VSYSTEMHARDCLASS],"%s",comm);
01117 
01118 strcat(comm," -n"); 
01119  
01120 if ((pp = cfpopen(comm,"r")) == NULL)
01121    {
01122    return;
01123    }
01124 
01125 while (!feof(pp))
01126    {
01127    bzero(local,bufsize);
01128    bzero(remote,bufsize);
01129    
01130    ReadLine(VBUFF,bufsize,pp);
01131 
01132    if (strstr(VBUFF,"UNIX"))
01133       {
01134       break;
01135       }
01136 
01137    if (!strstr(VBUFF,"."))
01138       {
01139       continue;
01140       }
01141 
01142    /* Different formats here ... ugh.. */
01143 
01144    if (strncmp(VBUFF,"tcp",3) == 0)
01145       {
01146       sscanf(VBUFF,"%*s %*s %*s %s %s",local,remote); /* linux-like */
01147       }
01148    else
01149       {
01150       sscanf(VBUFF,"%s %s",local,remote);             /* solaris-like */
01151       } 
01152 
01153    if (strlen(local) == 0)
01154       {
01155       continue;
01156       }