Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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);
    }
}
Beispiel #4
0
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);
}
Beispiel #5
0
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);
}
Beispiel #6
0
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);
}
Beispiel #7
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);
}
Beispiel #10
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);
}