static bool ShowHost(const char *hostkey, const char *address, bool incoming, const KeyHostSeen *quality, void *ctx) { int *count = ctx; char timebuf[26]; char hostname[CF_BUFSIZE]; strlcpy(hostname, IPString2Hostname(address), CF_BUFSIZE); (*count)++; printf("%-10.10s %-17.17s %-25.25s %-26.26s %-s\n", incoming ? "Incoming" : "Outgoing", address, hostname, cf_strtimestamp_local(quality->lastseen, timebuf), hostkey); return true; }
bool ShowHost(const char *hostkey, const char *address, bool incoming, const KeyHostSeen *quality, void *ctx) { int *count = ctx; char timebuf[26]; char hostname[MAXHOSTNAMELEN]; int ret = IPString2Hostname(hostname, address, sizeof(hostname)); (*count)++; printf("%-10.10s %-17.17s %-25.25s %-26.26s %-s\n", incoming ? "Incoming" : "Outgoing", address, (ret != -1) ? hostname : "-", cf_strtimestamp_local(quality->lastseen, timebuf), hostkey); return true; }
static void ShowState(char *type) { struct stat statbuf; char buffer[CF_BUFSIZE], vbuff[CF_BUFSIZE], assemble[CF_BUFSIZE]; Item *addresses = NULL, *saddresses = NULL, *ip; int i = 0, tot = 0, min_signal_diversity = 1, conns = 1; int maxlen = 0, count; double *dist = NULL, S = 0.0; char *offset = NULL; FILE *fp; CfDebug("ShowState(%s)\n", type); snprintf(buffer, CF_BUFSIZE - 1, "%s/state/cf_%s", CFWORKDIR, type); if (cfstat(buffer, &statbuf) == 0) { if ((fp = fopen(buffer, "r")) == NULL) { CfOut(cf_inform, "fopen", "Could not open state memory %s\n", buffer); return; } while (!feof(fp)) { char local[CF_BUFSIZE], remote[CF_BUFSIZE]; buffer[0] = local[0] = remote[0] = '\0'; memset(vbuff, 0, CF_BUFSIZE); fgets(buffer, CF_BUFSIZE, fp); if (strlen(buffer) > 0) { CfOut(cf_verbose, "", "(%2d) %s", conns, buffer); if (IsSocketType(type)) { if (strncmp(type, "incoming", 8) == 0 || strncmp(type, "outgoing", 8) == 0) { if (strncmp(buffer, "tcp", 3) == 0) { sscanf(buffer, "%*s %*s %*s %s %s", local, remote); /* linux-like */ } else { sscanf(buffer, "%s %s", local, remote); /* solaris-like */ } strncpy(vbuff, remote, CF_BUFSIZE - 1); DePort(vbuff); } } else if (IsTCPType(type)) { count = 1; sscanf(buffer, "%d %[^\n]", &count, remote); AppendItem(&addresses, remote, ""); SetItemListCounter(addresses, remote, count); conns += count; continue; } else { /* If we get here this is a process thing */ if (offset == NULL) { if ((offset = strstr(buffer, "CMD"))) { } else if ((offset = strstr(buffer, "COMMAND"))) { } if (offset == NULL) { continue; } } strncpy(vbuff, offset, CF_BUFSIZE - 1); Chop(vbuff); } if (!IsItemIn(addresses, vbuff)) { conns++; AppendItem(&addresses, vbuff, ""); IncrementItemListCounter(addresses, vbuff); } else { conns++; IncrementItemListCounter(addresses, vbuff); } } } fclose(fp); conns--; CfOut(cf_error, "", "\n"); CfOut(cf_error, "", "R: The peak measured state was q = %d:\n", conns); if (IsSocketType(type) || IsTCPType(type)) { for (ip = addresses; ip != NULL; ip = ip->next) { tot += ip->counter; buffer[0] = '\0'; sscanf(ip->name, "%s", buffer); if (!IsIPV4Address(buffer) && !IsIPV6Address(buffer)) { CfOut(cf_verbose, "", "Rejecting address %s\n", ip->name); continue; } CfOut(cf_error, "", "R: DNS key: %s = %s (%d/%d)\n", buffer, IPString2Hostname(buffer), ip->counter, conns); if (strlen(ip->name) > maxlen) { maxlen = strlen(ip->name); } } if (addresses != NULL) { printf("R: -\n"); } } else { for (ip = addresses; ip != NULL; ip = ip->next) { tot += ip->counter; } } addresses = SortItemListCounters(addresses); saddresses = addresses; for (ip = saddresses; ip != NULL; ip = ip->next) { int s; if (maxlen > 17) /* ipv6 */ { snprintf(assemble, CF_BUFSIZE, "Frequency: %-40s|", ip->name); } else { snprintf(assemble, CF_BUFSIZE, "Frequency: %-17s|", ip->name); } for (s = 0; (s < ip->counter) && (s < 50); s++) { if (s < 48) { strcat(assemble, "*"); } else { strcat(assemble, "+"); } } CfOut(cf_error, "", "R: %s \t(%d/%d)\n", assemble, ip->counter, conns); } dist = xmalloc((tot + 1) * sizeof(double)); if (conns > min_signal_diversity) { for (i = 0, ip = addresses; ip != NULL; i++, ip = ip->next) { dist[i] = ((double) (ip->counter)) / ((double) tot); S -= dist[i] * log(dist[i]); } CfOut(cf_error, "", "R: Variability/entropy of addresses = %.1f %%\n", S / log((double) tot) * 100.0); CfOut(cf_error, "", "R: (Entropy = 0 for single source, 100 for flatly distributed source)\n -\n"); } CfOut(cf_error, "", "\n"); CfOut(cf_error, "", "R: State of %s peaked at %s\n", type, cf_ctime(&statbuf.st_mtime)); } else { CfOut(cf_inform, "", "R: State parameter %s is not known or recorded\n", type); } DeleteItemList(addresses); if (dist) { free((char *) dist); } }
void PromiseMethod(struct Method *ptr) { struct Item *ip; int i,amserver; amserver = (IsItemIn(ptr->servers,IPString2Hostname(VFQNAME)) || IsItemIn(ptr->servers,IPString2UQHostname(VUQNAME)) || IsItemIn(ptr->servers,VIPADDRESS)); if (amserver) { printf("Promises to provide and execute method %s if context [%s]\n",ptr->name,ptr->classes); } else { printf("Promise to use voluntary service %s provided by server list if context [%s]\n",ptr->name,ptr->classes); i = 1; for (ip = ptr->send_args; ip != NULL; ip=ip->next) { printf(" Provide argument %d: %s\n",i++,ip->name); } printf(" %s\n",ChecksumPrint('m',ptr->digest)); i = 1; for (ip = ptr->send_classes; ip != NULL; ip=ip->next) { printf(" Provide class %d: %s\n",i++,ip->name); } i = 1; for (ip = ptr->servers; ip != NULL; ip=ip->next) { printf(" Encrypt for service provider %d: %s\n",i++,ip->name); } i = 1; if (ListLen(ptr->servers) > 1) { for (ip = ptr->return_vars; ip != NULL; ip=ip->next) { printf(" Return value %d: $(%s_X.%s) - X = 1,2,..\n",i++,ptr->name,ip->name); } i = 1; for (ip = ptr->return_classes; ip != NULL; ip=ip->next) { printf(" Will accept return class %d: %s_X_%s\n",i++,ptr->name,ip->name); } } else { for (ip = ptr->return_vars; ip != NULL; ip=ip->next) { printf(" Will accept return value %d: $(%s.%s)\n",i++,ptr->name,ip->name); } i = 1; for (ip = ptr->return_classes; ip != NULL; ip=ip->next) { printf(" Will accept return class %d: %s_%s\n",i++,ptr->name,ip->name); } } } printf(" IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); printf(" Using executable file: %s\n",ptr->file); printf(" Running with Uid=%d,Gid=%d\n",ptr->uid,ptr->gid); printf(" Running in chdir=%s, chroot=%s\n",ptr->chdir,ptr->chroot); printf(" Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); }
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 CheckFriendConnections(int hours) /* Go through the database of recent connections and check for Long Time No See ...*/ { DBT key,value; DB *dbp; DBC *dbcp; DB_ENV *dbenv = NULL; int ret, secs = CF_TICKS_PER_HOUR*hours, criterion, overdue, regex=false; time_t now = time(NULL),lsea = -1, tthen, then = 0; char name[CF_BUFSIZE],hostname[CF_BUFSIZE],datebuf[CF_MAXVARSIZE]; char addr[CF_BUFSIZE],type[CF_BUFSIZE], *regexp; struct QPoint entry; double average = 0.0, var = 0.0, ticksperminute = 60.0; double ticksperhour = (double)CF_TICKS_PER_HOUR,ticksperday = (double)CF_TICKS_PER_DAY; regex_t rx,rxcache; regmatch_t pmatch; if (regexp = GetMacroValue(CONTEXTID,"IgnoreFriendRegex")) { Verbose("IgnoreFriendRegex %s\n\n",regexp); if ((ret = regcomp(&rx,regexp,REG_EXTENDED)) != 0) { regerror(ret,&rx,name,1023); snprintf(OUTPUT,CF_BUFSIZE,"Regular expression error %d for %s: %s\n",ret,regexp,name); CfLog(cfinform,OUTPUT,""); regex = false; } else { regex = true; } } Verbose("CheckFriendConnections(%d)\n",hours); snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE); 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; } /* Acquire a cursor for the database. */ if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { CfLog(cferror,"Error reading from last-seen database",""); dbp->err(dbp, ret, "DB->cursor"); return; } /* Walk through the database and print out the key/data pairs. */ memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { memset(&entry, 0, sizeof(entry)); strcpy(hostname,(char *)key.data); if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); then = (time_t)entry.q; average = (double)entry.expect; var = (double)entry.var; } else { continue; } /* Got data, now get expiry criterion */ if (secs == 0) { /* Twice the average delta is significant */ criterion = (now - then > (int)(average+2.0*sqrt(var)+0.5)); overdue = now - then - (int)(average); } else { criterion = (now - then > secs); overdue = (now - then - secs); } if (GetMacroValue(CONTEXTID,"LastSeenExpireAfter")) { lsea = atoi(GetMacroValue(CONTEXTID,"LastSeenExpireAfter")); lsea *= CF_TICKS_PER_DAY; } if (lsea < 0) { lsea = (time_t)CF_WEEK/7; } if (regex) { if (regexec(&rx,IPString2Hostname(hostname+1),1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(hostname+1))) { Verbose("Not judging friend %s\n",hostname); criterion = false; lsea = CF_INFINITY; } } } tthen = (time_t)then; snprintf(datebuf,CF_BUFSIZE-1,"%s",ctime(&tthen)); datebuf[strlen(datebuf)-9] = '\0'; /* Chop off second and year */ snprintf(addr,15,"%s",hostname+1); switch(*hostname) { case '+': snprintf(type,CF_BUFSIZE,"last responded to hails"); break; case'-': snprintf(type,CF_BUFSIZE,"last hailed us"); break; } snprintf(OUTPUT,CF_BUFSIZE,"Host %s i.e. %s %s @ [%s] (overdue by %d mins)", IPString2Hostname(hostname+1), addr, type, datebuf, overdue/(int)ticksperminute); if (criterion) { CfLog(cferror,OUTPUT,""); } else { CfLog(cfverbose,OUTPUT,""); } snprintf(OUTPUT,CF_BUFSIZE,"i.e. (%.2f) hrs ago, Av %.2f +/- %.2f hrs\n", ((double)(now-then))/ticksperhour, average/ticksperhour, sqrt(var)/ticksperhour); if (criterion) { CfLog(cferror,OUTPUT,""); } else { CfLog(cfverbose,OUTPUT,""); } if ((now-then) > lsea) { snprintf(OUTPUT,CF_BUFSIZE,"Giving up on host %s -- too long since last seen",IPString2Hostname(hostname+1)); CfLog(cferror,OUTPUT,""); DeleteDB(dbp,hostname); } memset(&value,0,sizeof(value)); memset(&key,0,sizeof(key)); } dbcp->c_close(dbcp); dbp->close(dbp,0); }
void ShowLastSeenHosts() { CF_DB *dbp; CF_DBC *dbcp; char *key; void *value; char name[CF_BUFSIZE],hostname[CF_BUFSIZE],address[CF_MAXVARSIZE]; struct CfKeyHostSeen entry; int ksize,vsize; int count = 0; snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE); MapName(name); if (!OpenDB(name,&dbp)) { return; } /* Acquire a cursor for the database. */ if (!NewDBCursor(dbp,&dbcp)) { CfOut(cf_inform,""," !! Unable to scan last-seen database"); CloseDB(dbp); return; } /* Initialize the key/data return pair. */ printf("%9.9s %17.17s %-25.25s %15.15s\n","Direction","IP","Name","Key"); /* Walk through the database and print out the key/data pairs. */ while(NextDB(dbp,dbcp,&key,&ksize,&value,&vsize)) { if (value != NULL) { memset(&entry, 0, sizeof(entry)); memset(hostname, 0, sizeof(hostname)); memset(address, 0, sizeof(address)); memcpy(&entry,value,sizeof(entry)); strncpy(hostname,(char *)key,sizeof(hostname)-1); strncpy(address,(char *)entry.address,sizeof(address)-1); ++count; } else { continue; } CfOut(cf_verbose,""," -> Reporting on %s",hostname); printf("%-9.9s %17.17s %-25.25s %s\n", hostname[0] == '+' ? "Outgoing" : "Incoming", address, IPString2Hostname(address), hostname+1 ); } printf("Total Entries: %d\n",count); DeleteDBCursor(dbp,dbcp); CloseDB(dbp); }
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); }
static void VerifyFriendConnections(int hours,struct Attributes a,struct Promise *pp) /* Go through the database of recent connections and check for Long Time No See ...*/ { CF_DB *dbp; CF_DBC *dbcp; char *key; void *value; int ksize,vsize; int secs = SECONDS_PER_HOUR*hours, criterion, overdue; time_t now = time(NULL),lsea = (time_t)CF_WEEK, tthen, then; char name[CF_BUFSIZE],hostname[CF_BUFSIZE],datebuf[CF_MAXVARSIZE]; char addr[CF_BUFSIZE],type[CF_BUFSIZE],output[CF_BUFSIZE]; struct QPoint entry; double average = 0.0, var = 0.0, ticksperminute = 60.0; double ticksperhour = (double)SECONDS_PER_HOUR; CfOut(cf_verbose,"","CheckFriendConnections(%d)\n",hours); snprintf(name,CF_BUFSIZE-1,"%s/lastseen/%s",CFWORKDIR,CF_LASTDB_FILE); MapName(name); if (!OpenDB(name,&dbp)) { return; } /* Acquire a cursor for the database. */ if (!NewDBCursor(dbp,&dbcp)) { CfOut(cf_inform,""," !! Unable to scan friend db"); return; } /* Walk through the database and print out the key/data pairs. */ while(NextDB(dbp,dbcp,&key,&ksize,&value,&vsize)) { memset(&entry, 0, sizeof(entry)); strncpy(hostname,(char *)key,ksize); if (value != NULL) { memcpy(&entry,value,sizeof(entry)); then = (time_t)entry.q; average = (double)entry.expect; var = (double)entry.var; } else { continue; } if (then == 0) { continue; // No data } /* Got data, now get expiry criterion */ if (secs == 0) { /* Twice the average delta is significant */ criterion = (now - then > (int)(average+2.0*sqrt(var)+0.5)); overdue = now - then - (int)(average); } else { criterion = (now - then > secs); overdue = (now - then - secs); } if (LASTSEENEXPIREAFTER < 0) { lsea = (time_t)CF_WEEK; } else { lsea = LASTSEENEXPIREAFTER; } if (a.report.friend_pattern) { if (FullTextMatch(a.report.friend_pattern,IPString2Hostname(hostname+1))) { CfOut(cf_verbose,"","Not judging friend %s\n",hostname); criterion = false; lsea = CF_INFINITY; } } tthen = (time_t)then; snprintf(datebuf,CF_MAXVARSIZE-1,"%s",cf_ctime(&tthen)); datebuf[strlen(datebuf)-9] = '\0'; /* Chop off second and year */ snprintf(addr,15,"%s",hostname+1); switch(*hostname) { case '+': snprintf(type,CF_BUFSIZE,"last responded to hails"); break; case'-': snprintf(type,CF_BUFSIZE,"last hailed us"); break; } snprintf(output,CF_BUFSIZE,"Host %s i.e. %s %s @ [%s] (overdue by %d mins)", IPString2Hostname(hostname+1), addr, type, datebuf, overdue/(int)ticksperminute); if (criterion) { CfOut(cf_error,"",output); } else { CfOut(cf_verbose,"",output); } snprintf(output,CF_BUFSIZE,"i.e. (%.2f) hrs ago, Av %.2f +/- %.2f hrs\n", ((double)(now-then))/ticksperhour, average/ticksperhour, sqrt(var)/ticksperhour); if (criterion) { CfOut(cf_error,"",output); } else { CfOut(cf_verbose,"",output); } if (now - then > lsea) { CfOut(cf_error,"","Giving up on host %s -- %d hours since last seen",IPString2Hostname(hostname+1),hours); DeleteDB(dbp,hostname); } memset(&value,0,sizeof(value)); memset(&key,0,sizeof(key)); } DeleteDBCursor(dbp,dbcp); CloseDB(dbp); }
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); }