void MonitorStartServer(const Policy *policy, const ReportContext *report_context) { char timekey[CF_SMALLBUF]; Averages averages; Promise *pp = NewPromise("monitor_cfengine", "the monitor daemon"); Attributes dummyattr; CfLock thislock; #ifdef __MINGW32__ if (!NO_FORK) { CfOut(cf_verbose, "", "Windows does not support starting processes in the background - starting in foreground"); } #else /* !__MINGW32__ */ if ((!NO_FORK) && (fork() != 0)) { CfOut(cf_inform, "", "cf-monitord: starting\n"); _exit(0); } if (!NO_FORK) { ActAsDaemon(0); } #endif /* !__MINGW32__ */ memset(&dummyattr, 0, sizeof(dummyattr)); dummyattr.transaction.ifelapsed = 0; dummyattr.transaction.expireafter = 0; thislock = AcquireLock(pp->promiser, VUQNAME, CFSTARTTIME, dummyattr, pp, false); if (thislock.lock == NULL) { return; } WritePID("cf-monitord.pid"); MonNetworkSnifferOpen(); while (!IsPendingTermination()) { GetQ(policy, report_context); snprintf(timekey, sizeof(timekey), "%s", GenTimeKey(time(NULL))); averages = EvalAvQ(timekey); LeapDetection(); ArmClasses(averages, timekey); ZeroArrivals(); MonNetworkSnifferSniff(ITER, CF_THIS); ITER++; } }
int GetTimeSlot(time_t here_and_now) { time_t now; int slot = 0; char timekey[CF_MAXVARSIZE]; strcpy(timekey, GenTimeKey(here_and_now)); for (now = CF_MONDAY_MORNING; now < CF_MONDAY_MORNING + SECONDS_PER_WEEK; now += CF_MEASURE_INTERVAL, slot++) { if (strcmp(timekey, GenTimeKey(now)) == 0) { return slot; } } return -1; }
void MonitorStartServer(EvalContext *ctx, const Policy *policy) { char timekey[CF_SMALLBUF]; Averages averages; Policy *monitor_cfengine_policy = PolicyNew(); Promise *pp = NULL; { Bundle *bp = PolicyAppendBundle(monitor_cfengine_policy, NamespaceDefault(), "monitor_cfengine_bundle", "agent", NULL, NULL); PromiseType *tp = BundleAppendPromiseType(bp, "monitor_cfengine"); pp = PromiseTypeAppendPromise(tp, "the monitor daemon", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, NULL); } assert(pp); CfLock thislock; #ifdef __MINGW32__ if (!NO_FORK) { Log(LOG_LEVEL_VERBOSE, "Windows does not support starting processes in the background - starting in foreground"); } #else /* !__MINGW32__ */ if ((!NO_FORK) && (fork() != 0)) { Log(LOG_LEVEL_INFO, "cf-monitord: starting"); _exit(0); } if (!NO_FORK) { ActAsDaemon(0); } #endif /* !__MINGW32__ */ TransactionContext tc = { .ifelapsed = 0, .expireafter = 0, }; thislock = AcquireLock(ctx, pp->promiser, VUQNAME, CFSTARTTIME, tc, pp, false); if (thislock.lock == NULL) { PolicyDestroy(monitor_cfengine_policy); return; } WritePID("cf-monitord.pid"); MonNetworkSnifferOpen(); while (!IsPendingTermination()) { GetQ(ctx, policy); snprintf(timekey, sizeof(timekey), "%s", GenTimeKey(time(NULL))); averages = EvalAvQ(ctx, timekey); LeapDetection(); ArmClasses(averages, timekey); ZeroArrivals(); MonNetworkSnifferSniff(ITER, CF_THIS); ITER++; } PolicyDestroy(monitor_cfengine_policy); } /*********************************************************************/ static void GetQ(EvalContext *ctx, const Policy *policy) { MonEntropyClassesReset(); ZeroArrivals(); MonProcessesGatherData(CF_THIS); #ifndef __MINGW32__ MonCPUGatherData(CF_THIS); MonLoadGatherData(CF_THIS); MonDiskGatherData(CF_THIS); MonNetworkGatherData(CF_THIS); MonNetworkSnifferGatherData(); MonTempGatherData(CF_THIS); #endif /* !__MINGW32__ */ MonOtherGatherData(CF_THIS); GatherPromisedMeasures(ctx, policy); }
void UpdateLastSeen() // This function is temporarily or permanently deprecated { double lsea = LASTSEENEXPIREAFTER; int intermittency = false,qsize,ksize; struct CfKeyHostSeen q,newq; double lastseen,delta2; void *stored; CF_DB *dbp = NULL,*dbpent = NULL; CF_DBC *dbcp; char name[CF_BUFSIZE],*key; struct Rlist *rp; struct CfKeyBinding *kp; time_t now = time(NULL); static time_t then; if (now < then + 300 && then > 0 && then <= now + 300) { // Rate limiter return; } then = now; CfOut(cf_verbose,""," -> Writing last-seen observations"); ThreadLock(cft_server_keyseen); if (SERVER_KEYSEEN == NULL) { ThreadUnlock(cft_server_keyseen); CfOut(cf_verbose,""," -> Keyring is empty"); return; } if (BooleanControl("control_agent",CFA_CONTROLBODY[cfa_intermittency].lval)) { CfOut(cf_inform,""," -> Recording intermittency"); intermittency = true; } snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE); MapName(name); if (!OpenDB(name,&dbp)) { ThreadUnlock(cft_server_keyseen); return; } /* First scan for hosts that have moved address and purge their records so that the database always has a 1:1 relationship between keyhash and IP address */ if (!NewDBCursor(dbp,&dbcp)) { ThreadUnlock(cft_server_keyseen); CfOut(cf_inform,""," !! Unable to scan class db"); return; } while(NextDB(dbp,dbcp,&key,&ksize,&stored,&qsize)) { memcpy(&q,stored,sizeof(q)); lastseen = (double)now - q.Q.q; if (lastseen > lsea) { CfOut(cf_verbose,""," -> Last-seen record for %s expired after %.1lf > %.1lf hours\n",key,lastseen/3600,lsea/3600); DeleteDB(dbp,key); } for (rp = SERVER_KEYSEEN; rp != NULL; rp=rp->next) { kp = (struct CfKeyBinding *) rp->item; if ((strcmp(q.address,kp->address) == 0) && (strcmp(key+1,kp->name+1) != 0)) { CfOut(cf_verbose,""," ! Deleting %s's address (%s=%d) as this host %s seems to have moved elsewhere (%s=5d)",key,kp->address,strlen(kp->address),kp->name,q.address,strlen(q.address)); DeleteDB(dbp,key); } } } DeleteDBCursor(dbp,dbcp); /* Now perform updates with the latest data */ for (rp = SERVER_KEYSEEN; rp != NULL; rp=rp->next) { kp = (struct CfKeyBinding *) rp->item; now = kp->timestamp; if (intermittency) { /* Open special file for peer entropy record - INRIA intermittency */ snprintf(name,CF_BUFSIZE-1,"%s/lastseen/%s.%s",CFWORKDIR,CF_LASTDB_FILE,kp->name); MapName(name); if (!OpenDB(name,&dbpent)) { continue; } } if (ReadDB(dbp,kp->name,&q,sizeof(q))) { lastseen = (double)now - q.Q.q; if (q.Q.q <= 0) { lastseen = 300; q.Q.expect = 0; q.Q.var = 0; } newq.Q.q = (double)now; newq.Q.expect = GAverage(lastseen,q.Q.expect,0.4); delta2 = (lastseen - q.Q.expect)*(lastseen - q.Q.expect); newq.Q.var = GAverage(delta2,q.Q.var,0.4); strncpy(newq.address,kp->address,CF_ADDRSIZE-1); } else { lastseen = 0.0; newq.Q.q = (double)now; newq.Q.expect = 0.0; newq.Q.var = 0.0; strncpy(newq.address,kp->address,CF_ADDRSIZE-1); } if (lastseen > lsea) { CfOut(cf_verbose,""," -> Last-seen record for %s expired after %.1lf > %.1lf hours\n",kp->name,lastseen/3600,lsea/3600); DeleteDB(dbp,kp->name); } else { char timebuf[26]; CfOut(cf_verbose,""," -> Last saw %s (alias %s) at %s (noexpiry %.1lf <= %.1lf)\n",kp->name,kp->address,cf_strtimestamp_local(now,timebuf),lastseen/3600,lsea/3600); WriteDB(dbp,kp->name,&newq,sizeof(newq)); if (intermittency) { WriteDB(dbpent,GenTimeKey(now),&newq,sizeof(newq)); } } if (intermittency && dbpent) { CloseDB(dbpent); } } ThreadUnlock(cft_server_keyseen); }
void CheckFriendReliability() { DBT key,value; DB *dbp,*dbpent; DBC *dbcp; DB_ENV *dbenv = NULL, *dbenv2 = NULL; int i,ret; double n[CF_RELIABLE_CLASSES],n_av[CF_RELIABLE_CLASSES],total; double p[CF_RELIABLE_CLASSES],p_av[CF_RELIABLE_CLASSES]; char name[CF_BUFSIZE],hostname[CF_BUFSIZE],timekey[CF_MAXVARSIZE]; struct QPoint entry; struct Item *ip, *hostlist = NULL; double entropy,average,var,sum,sum_av,expect,actual; time_t now = time(NULL), then, lastseen = CF_WEEK; Verbose("CheckFriendReliability()\n"); snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE); average = (double) CF_HOUR; /* It will take a week for a host to be deemed reliable */ var = 0; if ((errno = db_create(&dbp,dbenv,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { CfLog(cferror,"Error reading from last-seen database",""); dbp->err(dbp, ret, "DB->cursor"); return; } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { strcpy(hostname,IPString2Hostname((char *)key.data+1)); if (!IsItemIn(hostlist,hostname)) { /* Check hostname not recorded twice with +/- */ AppendItem(&hostlist,hostname,NULL); Verbose(" Measuring reliability of %s\n",hostname); } } dbcp->c_close(dbcp); dbp->close(dbp,0); /* Now go through each host and recompute entropy */ for (ip = hostlist; ip != NULL; ip=ip->next) { snprintf(name,CF_BUFSIZE-1,"%s/%s.%s",CFWORKDIR,CF_LASTDB_FILE,ip->name); if ((errno = db_create(&dbpent,dbenv2,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't init reliability profile database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbpent->open)(dbpent,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbpent->open)(dbpent,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); continue; } for (i = 0; i < CF_RELIABLE_CLASSES; i++) { n[i] = n_av[i] = 0.0; } total = 0.0; for (now = CF_MONDAY_MORNING; now < CF_MONDAY_MORNING+CF_WEEK; now += CF_MEASURE_INTERVAL) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); strcpy(timekey,GenTimeKey(now)); key.data = timekey; key.size = strlen(timekey)+1; if ((errno = dbp->get(dbp,NULL,&key,&value,0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp,errno,NULL); exit(1); } } if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); then = (time_t)entry.q; lastseen = now - then; if (lastseen < 0) { lastseen = 0; /* Never seen before, so pretend */ } average = (double)entry.expect; var = (double)entry.var; Debug("%s => then = %ld, lastseen = %ld, average=%.2f\n",hostname,then,lastseen,average); } else { /* If we have no data, it means no contact for whatever reason. It could be unable to respond unwilling to respond, policy etc. Assume for argument that we expect regular responses ... */ lastseen += CF_MEASURE_INTERVAL; /* infer based on no data */ } for (i = 0; i < CF_RELIABLE_CLASSES; i++) { if (lastseen >= i*CF_HOUR && lastseen < (i+1)*CF_HOUR) { n[i]++; } if (average >= (double)(i*CF_HOUR) && average < (double)((i+1)*CF_HOUR)) { n_av[i]++; } } total++; } sum = sum_av = 0.0; for (i = 0; i < CF_RELIABLE_CLASSES; i++) { p[i] = n[i]/total; p_av[i] = n_av[i]/total; sum += p[i]; sum_av += p_av[i]; } Debug("Reliabilities sum to %.2f av %.2f\n\n",sum,sum_av); sum = sum_av = 0.0; for (i = 0; i < CF_RELIABLE_CLASSES; i++) { if (p[i] == 0.0) { continue; } sum -= p[i] * log(p[i]); } for (i = 0; i < CF_RELIABLE_CLASSES; i++) { if (p_av[i] == 0.0) { continue; } sum_av -= p_av[i] * log(p_av[i]); } actual = sum/log((double)CF_RELIABLE_CLASSES)*100.0; expect = sum_av/log((double)CF_RELIABLE_CLASSES)*100.0; Verbose("Scaled entropy for %s = %.1f %%\n",ip->name,actual); Verbose("Expected entropy for %s = %.1f %%\n\n",ip->name,expect); if (actual > expect) { snprintf(OUTPUT,CF_BUFSIZE,"The reliability of %s has decreased!\n",ip->name); CfLog(cfinform,OUTPUT,""); } if (actual > 50.0) { snprintf(OUTPUT,CF_BUFSIZE,"FriendStatus reports the intermittency of %s above 50%% (scaled entropy units)\n",ip->name); CfLog(cferror,OUTPUT,""); } if (expect > actual) { snprintf(OUTPUT,CF_BUFSIZE,"The reliability of %s seems to be improving!\n",ip->name); CfLog(cfinform,OUTPUT,""); } dbpent->close(dbpent,0); } DeleteItemList(hostlist); }
void LastSeen(char *hostname,enum roles role) { DB *dbp,*dbpent; DB_ENV *dbenv = NULL, *dbenv2 = NULL; char name[CF_BUFSIZE],databuf[CF_BUFSIZE]; time_t now = time(NULL); struct QPoint q,newq; double lastseen,delta2; int lsea = -1; if (strlen(hostname) == 0) { snprintf(OUTPUT,CF_BUFSIZE,"LastSeen registry for empty hostname with role %d",role); CfLog(cflogonly,OUTPUT,""); return; } Debug("LastSeen(%s) reg\n",hostname); /* Tidy old versions - temporary */ snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_OLDLASTDB_FILE); unlink(name); if ((errno = db_create(&dbp,dbenv,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't init last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE); #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } /* Now open special file for peer entropy record - INRIA intermittency */ snprintf(name,CF_BUFSIZE-1,"%s/%s.%s",CFWORKDIR,CF_LASTDB_FILE,hostname); if ((errno = db_create(&dbpent,dbenv2,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't init last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbpent->open)(dbpent,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbpent->open)(dbpent,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef HAVE_PTHREAD_H if (pthread_mutex_lock(&MUTEX_GETADDR) != 0) { CfLog(cferror,"pthread_mutex_lock failed","unlock"); exit(1); } #endif switch (role) { case cf_accept: snprintf(databuf,CF_BUFSIZE-1,"-%s",Hostname2IPString(hostname)); break; case cf_connect: snprintf(databuf,CF_BUFSIZE-1,"+%s",Hostname2IPString(hostname)); break; } #ifdef HAVE_PTHREAD_H if (pthread_mutex_unlock(&MUTEX_GETADDR) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","unlock"); exit(1); } #endif if (GetMacroValue(CONTEXTID,"LastSeenExpireAfter")) { lsea = atoi(GetMacroValue(CONTEXTID,"LastSeenExpireAfter")); lsea *= CF_TICKS_PER_DAY; } if (lsea < 0) { lsea = CF_WEEK; } if (ReadDB(dbp,databuf,&q,sizeof(q))) { lastseen = (double)now - q.q; newq.q = (double)now; /* Last seen is now-then */ newq.expect = GAverage(lastseen,q.expect,0.3); delta2 = (lastseen - q.expect)*(lastseen - q.expect); newq.var = GAverage(delta2,q.var,0.3); } else { lastseen = 0.0; newq.q = (double)now; newq.expect = 0.0; newq.var = 0.0; } #ifdef HAVE_PTHREAD_H if (pthread_mutex_lock(&MUTEX_GETADDR) != 0) { CfLog(cferror,"pthread_mutex_lock failed","unlock"); exit(1); } #endif if (lastseen > (double)lsea) { Verbose("Last seen %s expired\n",databuf); DeleteDB(dbp,databuf); } else { WriteDB(dbp,databuf,&newq,sizeof(newq)); WriteDB(dbpent,GenTimeKey(now),&newq,sizeof(newq)); } #ifdef HAVE_PTHREAD_H if (pthread_mutex_unlock(&MUTEX_GETADDR) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","unlock"); exit(1); } #endif dbp->close(dbp,0); dbpent->close(dbpent,0); }
void PeerIntermittency() { DBT key,value; DB *dbp,*dbpent; DBC *dbcp; DB_ENV *dbenv = NULL, *dbenv2 = NULL; int i,ret; FILE *fp1,*fp2; char name[CF_BUFSIZE],hostname[CF_BUFSIZE],timekey[CF_MAXVARSIZE]; char out1[CF_BUFSIZE],out2[CF_BUFSIZE]; struct QPoint entry; struct Item *ip, *hostlist = NULL; double entropy,average,var,sum,sum_av; time_t now = time(NULL), then, lastseen = CF_WEEK; snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE); average = (double) CF_HOUR; /* It will take a week for a host to be deemed reliable */ var = 0; if ((errno = db_create(&dbp,dbenv,0)) != 0) { Verbose("Couldn't open last-seen database %s\n",name); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { Verbose("Couldn't open last-seen database %s\n",name); dbp->close(dbp,0); return; } if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { Verbose("Error reading from last-seen database\n"); dbp->err(dbp, ret, "DB->cursor"); return; } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); Verbose("Examining known peers...\n"); while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { strcpy(hostname,IPString2Hostname((char *)key.data+1)); if (!IsItemIn(hostlist,hostname)) { /* Check hostname not recorded twice with +/- */ AppendItem(&hostlist,hostname,NULL); Verbose("Examining intermittent host %s\n",hostname); } } dbcp->c_close(dbcp); dbp->close(dbp,0); /* Now go through each host and recompute entropy */ for (ip = hostlist; ip != NULL; ip=ip->next) { snprintf(out1,CF_BUFSIZE,"lastseen-%s.q",ip->name); Verbose("Opening %s\n",out1); if ((fp1 = fopen(out1,"w")) == NULL) { Verbose("Unable to open %s\n",out1); continue; } snprintf(out2,CF_BUFSIZE,"lastseen-%s.E-sigma",hostname); if ((fp2 = fopen(out2,"w")) == NULL) { Verbose("Unable to open %s\n",out1); continue; } snprintf(name,CF_BUFSIZE-1,"%s/%s.%s",CFWORKDIR,CF_LASTDB_FILE,ip->name); Verbose("Consulting profile %s\n",name); if ((errno = db_create(&dbpent,dbenv2,0)) != 0) { Verbose("Couldn't init reliability profile database %s\n",name); return; } #ifdef CF_OLD_DB if ((errno = (dbpent->open)(dbpent,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbpent->open)(dbpent,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { Verbose("Couldn't open last-seen database %s\n",name); continue; } for (now = CF_MONDAY_MORNING; now < CF_MONDAY_MORNING+CF_WEEK; now += CF_MEASURE_INTERVAL) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); strcpy(timekey,GenTimeKey(now)); key.data = timekey; key.size = strlen(timekey)+1; if ((errno = dbpent->get(dbpent,NULL,&key,&value,0)) != 0) { if (errno != DB_NOTFOUND) { dbpent->err(dbp,errno,NULL); exit(1); } } if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); then = (time_t)entry.q; lastseen = now - then; if (lastseen < 0) { lastseen = 0; /* Never seen before, so pretend */ } average = (double)entry.expect; var = (double)entry.var; fprintf(fp2,"%d %lf %lf\n",now,average,sqrt(var)); } else { /* If we have no data, it means no contact for whatever reason. It could be unable to respond unwilling to respond, policy etc. Assume for argument that we expect regular responses ... */ lastseen += CF_MEASURE_INTERVAL; /* infer based on no data */ } fprintf(fp1,"%d %d\n",now,lastseen); } fclose(fp1); fclose(fp2); dbpent->close(dbpent,0); } DeleteItemList(hostlist); }
static void VerifyFriendReliability(struct Attributes a,struct Promise *pp) { CF_DB *dbp; CF_DBC *dbcp; int i,ksize,vsize; char *key; void *value; double n[CF_RELIABLE_CLASSES],n_av[CF_RELIABLE_CLASSES],total; double p[CF_RELIABLE_CLASSES],p_av[CF_RELIABLE_CLASSES]; char name[CF_BUFSIZE],hostname[CF_BUFSIZE],timekey[CF_MAXVARSIZE]; struct QPoint entry; struct Item *ip, *hostlist = NULL; double average,var,sum,sum_av,expect,actual; time_t now = time(NULL), then, lastseen = CF_WEEK; CfOut(cf_verbose,"","CheckFriendReliability()\n"); snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE); average = (double) CF_HOUR; /* It will take a week for a host to be deemed reliable */ var = 0; if (!OpenDB(name,&dbp)) { return; } if (!NewDBCursor(dbp,&dbcp)) { CfOut(cf_inform,""," !! Unable to scan last-seen db"); return; } while(NextDB(dbp,dbcp,&key,&ksize,&value,&vsize)) { strcpy(hostname,IPString2Hostname((char *)key+1)); if (!IsItemIn(hostlist,hostname)) { /* Check hostname not recorded twice with +/- */ AppendItem(&hostlist,hostname,NULL); CfOut(cf_verbose,""," Measuring reliability of %s\n",hostname); } } DeleteDBCursor(dbp,dbcp); CloseDB(dbp); /* Now go through each host and recompute entropy */ for (ip = hostlist; ip != NULL; ip=ip->next) { snprintf(name,CF_BUFSIZE-1,"%s/%s.%s",CFWORKDIR,CF_LASTDB_FILE,ip->name); MapName(name); if (!OpenDB(name,&dbp)) { return; } for (i = 0; i < CF_RELIABLE_CLASSES; i++) { n[i] = n_av[i] = 0.0; } total = 0.0; for (now = CF_MONDAY_MORNING; now < CF_MONDAY_MORNING+CF_WEEK; now += CF_MEASURE_INTERVAL) { strcpy(timekey,GenTimeKey(now)); if (ReadDB(dbp,timekey,&value,sizeof(entry))) { memcpy(&entry,value,sizeof(entry)); then = (time_t)entry.q; lastseen = now - then; if (lastseen < 0) { lastseen = 0; /* Never seen before, so pretend */ } average = (double)entry.expect; var = (double)entry.var; Debug("%s => then = %ld, lastseen = %ld, average=%.2f\n",hostname,then,lastseen,average); } else { /* If we have no data, it means no contact for whatever reason. It could be unable to respond unwilling to respond, policy etc. Assume for argument that we expect regular responses ... */ lastseen += CF_MEASURE_INTERVAL; /* infer based on no data */ } for (i = 0; i < CF_RELIABLE_CLASSES; i++) { if (lastseen >= i*CF_HOUR && lastseen < (i+1)*CF_HOUR) { n[i]++; } if (average >= (double)(i*CF_HOUR) && average < (double)((i+1)*CF_HOUR)) { n_av[i]++; } } total++; } sum = sum_av = 0.0; for (i = 0; i < CF_RELIABLE_CLASSES; i++) { p[i] = n[i]/total; p_av[i] = n_av[i]/total; sum += p[i]; sum_av += p_av[i]; } Debug("Reliabilities sum to %.2f av %.2f\n\n",sum,sum_av); sum = sum_av = 0.0; for (i = 0; i < CF_RELIABLE_CLASSES; i++) { if (p[i] == 0.0) { continue; } sum -= p[i] * log(p[i]); } for (i = 0; i < CF_RELIABLE_CLASSES; i++) { if (p_av[i] == 0.0) { continue; } sum_av -= p_av[i] * log(p_av[i]); } actual = sum/log((double)CF_RELIABLE_CLASSES)*100.0; expect = sum_av/log((double)CF_RELIABLE_CLASSES)*100.0; CfOut(cf_verbose,"","Scaled entropy for %s = %.1f %%\n",ip->name,actual); CfOut(cf_verbose,"","Expected entropy for %s = %.1f %%\n\n",ip->name,expect); if (actual > expect) { CfOut(cf_inform,""," !! The reliability of %s deteriorated\n",ip->name); } if (actual > 50.0) { CfOut(cf_error,"","FriendStatus reports the intermittency of %s above 50%% (SEUs)\n",ip->name); } if (expect > actual) { CfOut(cf_inform,"","The reliability of %s is improved\n",ip->name); } CloseDB(dbp); } DeleteItemList(hostlist); }
void DiskArrivals(void) { DIR *dirh; FILE *fp; struct dirent *dirp; int count = 0, index = 0, i; char filename[CF_BUFSIZE],database[CF_BUFSIZE]; double val, maxval = 1.0, *array, grain = 0.0; time_t now; DBT key,value; DB *dbp = NULL; DB_ENV *dbenv = NULL; if ((array = (double *)malloc((int)CF_WEEK)) == NULL) { Verbose("Memory error"); perror("malloc"); return; } if ((dirh = opendir(CFWORKDIR)) == NULL) { Verbose("Can't open directory %s\n",CFWORKDIR); perror("opendir"); return; } Verbose("\n\nLooking for filesystem arrival process data in %s\n",CFWORKDIR); for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (strncmp(dirp->d_name,"scan:",5) == 0) { Verbose("Found %s - generating X,Y plot\n",dirp->d_name); snprintf(database,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,dirp->d_name); if ((ERRNO = db_create(&dbp,dbenv,0)) != 0) { Verbose("Couldn't open arrivals database %s\n",database); return; } #ifdef CF_OLD_DB if ((ERRNO = (dbp->open)(dbp,database,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((ERRNO = (dbp->open)(dbp,NULL,database,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { Verbose("Couldn't open database %s\n",database); dbp->close(dbp,0); continue; } maxval = 1.0; grain = 0.0; count = 0.0; index = 0; for (now = CF_MONDAY_MORNING; now < CF_MONDAY_MORNING+CF_WEEK; now += CF_MEASURE_INTERVAL) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); strcpy(TIMEKEY,GenTimeKey(now)); key.data = TIMEKEY; key.size = strlen(TIMEKEY)+1; if ((ERRNO = dbp->get(dbp,NULL,&key,&value,0)) != 0) { if (ERRNO != DB_NOTFOUND) { DBP->err(DBP,ERRNO,NULL); exit(1); } } if (value.data != NULL) { grain += (double)*(double *)(value.data); } else { grain = 0; } if (HIRES) { if (grain > maxval) { maxval = grain; } array[index] = grain; grain = 0.0; index++; } else { if (count % 12 == 0) { if (grain > maxval) { maxval = grain; } array[index] = grain; index++; grain = 0.0; } } count++; } dbp->close(dbp,0); snprintf(filename,CF_BUFSIZE-1,"%s.cfenv",dirp->d_name); if ((fp = fopen(filename,"w")) == NULL) { Verbose("Unable to open %s for writing\n",filename); perror("fopen"); return; } Verbose("Data points = %d\n",index); for (i = 0; i < index; i++) { if (i > 1 && i < index-1) { val = (array[i-1]+array[i]+array[i+1])/3.0; /* Smoothing */ } else { val = array[i]; } fprintf(fp,"%d %f\n",i,val/maxval*50.0); } fclose(fp); } } closedir(dirh); }
void MagnifyNow() { int its,i,j,k, count = 0; DBT key,value; time_t now; OpenMagnifyFiles(); its = 1; /* detailed view */ now = time(NULL); NOW = now - (time_t)(4 * CF_TICKS_PER_HOUR); while (NOW < now) { memset(&ENTRY,0,sizeof(ENTRY)); for (j = 0; j < its; j++) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); strcpy(TIMEKEY,GenTimeKey(NOW)); key.data = TIMEKEY; key.size = strlen(TIMEKEY)+1; if ((ERRNO = DBP->get(DBP,NULL,&key,&value,0)) != 0) { if (ERRNO != DB_NOTFOUND) { DBP->err(DBP,ERRNO,NULL); exit(1); } } /* Work out local average over grain size "its" */ if (value.data != NULL) { memcpy(&DET,value.data,sizeof(DET)); for (i = 0; i < CF_OBSERVABLES; i++) { ENTRY.Q[i].expect += DET.Q[i].expect/(double)its; ENTRY.Q[i].var += DET.Q[i].var/(double)its; ENTRY.Q[i].q += DET.Q[i].q/(double)its; } if (NOSCALING) { for (i = 1; i < CF_OBSERVABLES; i++) { MAX.Q[i].expect = 1; MAX.Q[i].q = 1; } } } NOW += CF_MEASURE_INTERVAL; count++; } /* Output q and E/sig data in a plethora of files */ for (i = 0; i < CF_OBSERVABLES; i++) { fprintf(FPM[i],"%d %f %f %f\n",count, ENTRY.Q[i].expect, sqrt(ENTRY.Q[i].var),ENTRY.Q[i].q); } } DBP->close(DBP,0); CloseMagnifyFiles(); }
void WriteGraphFiles() { int its,i,j,k, count = 0; DBT key,value; struct stat statbuf; OpenFiles(); if (TITLES) { for (i = 0; i < CF_OBSERVABLES; i+=2) { fprintf(FPAV,"# Column %d: %s\n",i,OBS[i][0]); fprintf(FPVAR,"# Column %d: %s\n",i,OBS[i][0]); fprintf(FPNOW,"# Column %d: %s\n",i,OBS[i][0]); } fprintf(FPAV,"##############################################\n"); fprintf(FPVAR,"##############################################\n"); fprintf(FPNOW,"##############################################\n"); } if (HIRES) { its = 1; } else { its = 12; } NOW = CF_MONDAY_MORNING; memset(&ENTRY,0,sizeof(ENTRY)); while (NOW < CF_MONDAY_MORNING+CF_WEEK) { for (j = 0; j < its; j++) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); strcpy(TIMEKEY,GenTimeKey(NOW)); key.data = TIMEKEY; key.size = strlen(TIMEKEY)+1; if ((ERRNO = DBP->get(DBP,NULL,&key,&value,0)) != 0) { if (ERRNO != DB_NOTFOUND) { DBP->err(DBP,ERRNO,NULL); exit(1); } } /* Work out local average over grain size "its" */ if (value.data != NULL) { memcpy(&DET,value.data,sizeof(DET)); for (i = 0; i < CF_OBSERVABLES; i++) { ENTRY.Q[i].expect += DET.Q[i].expect/(double)its; ENTRY.Q[i].var += DET.Q[i].var/(double)its; ENTRY.Q[i].q += DET.Q[i].q/(double)its; } if (NOSCALING) { for (i = 1; i < CF_OBSERVABLES; i++) { MAX.Q[i].expect = 1; MAX.Q[i].q = 1; } } } NOW += CF_MEASURE_INTERVAL; count++; } /* Output the data in a plethora of files */ fprintf(FPAV,"%d ",count); fprintf(FPVAR,"%d ",count); fprintf(FPNOW,"%d ",count); for (i = 0; i < CF_OBSERVABLES; i++) { fprintf(FPAV,"%f ",ENTRY.Q[i].expect/MAX.Q[i].expect); fprintf(FPVAR,"%f ",ENTRY.Q[i].var/MAX.Q[i].var); fprintf(FPNOW,"%f ",ENTRY.Q[i].q/MAX.Q[i].q); } fprintf(FPAV,"\n"); fprintf(FPVAR,"\n"); fprintf(FPNOW,"\n"); if (SEPARATE) { for (i = 0; i < CF_OBSERVABLES; i++) { fprintf(FPE[i],"%d %f %f\n",count, ENTRY.Q[i].expect, sqrt(ENTRY.Q[i].var)); /* Use same scaling for Q so graphs can be merged */ fprintf(FPQ[i],"%d %f 0.0\n",count, ENTRY.Q[i].q); } } memset(&ENTRY,0,sizeof(ENTRY)); } DBP->close(DBP,0); CloseFiles(); }
void EraseAverages() { int i; DBT key,value; struct Item *list = NULL; Verbose("\nLooking through current database %s\n",FILENAME); list = SplitStringAsItemList(ERASE,','); if ((ERRNO = db_create(&DBP,NULL,0)) != 0) { Verbose("Couldn't create average database %s\n",FILENAME); exit(1); } #ifdef CF_OLD_DB if ((ERRNO = (DBP->open)(DBP,FILENAME,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((ERRNO = (DBP->open)(DBP,NULL,FILENAME,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { Verbose("Couldn't open average database %s\n",FILENAME); DBP->err(DBP,ERRNO,NULL); exit(1); } memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); for (i = 0; i < CF_OBSERVABLES; i++) { FPE[i] = FPQ[i] = NULL; } for (NOW = CF_MONDAY_MORNING; NOW < CF_MONDAY_MORNING+CF_WEEK; NOW += CF_MEASURE_INTERVAL) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); memset(&ENTRY,0,sizeof(ENTRY)); strcpy(TIMEKEY,GenTimeKey(NOW)); key.data = TIMEKEY; key.size = strlen(TIMEKEY)+1; if ((ERRNO = DBP->get(DBP,NULL,&key,&value,0)) != 0) { if (ERRNO != DB_NOTFOUND) { DBP->err(DBP,ERRNO,NULL); exit(1); } } if (value.data != NULL) { memcpy(&ENTRY,value.data,sizeof(ENTRY)); for (i = 0; i < CF_OBSERVABLES; i++) { if (IsItemIn(list,OBS[i][0])) { /* Set history but not most recent to zero */ ENTRY.Q[i].expect = 0; ENTRY.Q[i].var = 0; } } value.data = &ENTRY; if ((ERRNO = DBP->put(DBP,NULL,&key,&value,0)) != 0) { DBP->err(DBP,ERRNO,NULL); exit(1); } } } DBP->close(DBP,0); }
void ReadAverages() { int i; DBT key,value; Verbose("\nLooking for database %s\n",FILENAME); Verbose("\nFinding MAXimum values...\n\n"); Verbose("N.B. socket values are numbers in CLOSE_WAIT. See documentation.\n"); if ((ERRNO = db_create(&DBP,NULL,0)) != 0) { Verbose("Couldn't create average database %s\n",FILENAME); exit(1); } #ifdef CF_OLD_DB if ((ERRNO = (DBP->open)(DBP,FILENAME,NULL,DB_BTREE,DB_RDONLY,0644)) != 0) #else if ((ERRNO = (DBP->open)(DBP,NULL,FILENAME,NULL,DB_BTREE,DB_RDONLY,0644)) != 0) #endif { Verbose("Couldn't open average database %s\n",FILENAME); DBP->err(DBP,ERRNO,NULL); exit(1); } for (i = 0; i < CF_OBSERVABLES; i++) { MAX.Q[i].var = MAX.Q[i].expect = MAX.Q[i].q = 0.01; MIN.Q[i].var = MIN.Q[i].expect = MIN.Q[i].q = 9999.0; FPE[i] = FPQ[i] = NULL; } for (NOW = CF_MONDAY_MORNING; NOW < CF_MONDAY_MORNING+CF_WEEK; NOW += CF_MEASURE_INTERVAL) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); memset(&ENTRY,0,sizeof(ENTRY)); strcpy(TIMEKEY,GenTimeKey(NOW)); key.data = TIMEKEY; key.size = strlen(TIMEKEY)+1; if ((ERRNO = DBP->get(DBP,NULL,&key,&value,0)) != 0) { if (ERRNO != DB_NOTFOUND) { DBP->err(DBP,ERRNO,NULL); exit(1); } } if (value.data != NULL) { memcpy(&ENTRY,value.data,sizeof(ENTRY)); for (i = 0; i < CF_OBSERVABLES; i++) { if (fabs(ENTRY.Q[i].expect) > MAX.Q[i].expect) { MAX.Q[i].expect = fabs(ENTRY.Q[i].expect); } if (fabs(ENTRY.Q[i].q) > MAX.Q[i].q) { MAX.Q[i].q = fabs(ENTRY.Q[i].q); } if (fabs(ENTRY.Q[i].expect) < MIN.Q[i].expect) { MIN.Q[i].expect = fabs(ENTRY.Q[i].expect); } if (fabs(ENTRY.Q[i].q) < MIN.Q[i].q) { MIN.Q[i].q = fabs(ENTRY.Q[i].q); } } } } DBP->close(DBP,0); }