"Fossies" - the Fresh Open Source Software Archive

Member "bandwidthd-2.0.1/graph.c" (11 Jan 2005, 33543 Bytes) of package /linux/privat/old/bandwidthd-2.0.1.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "graph.c" see the Fossies "Dox" file reference documentation.

    1 #include <unistd.h>
    2 #include <setjmp.h>
    3 #include <signal.h>
    4 #include <string.h>
    5 #include <netdb.h>
    6 #include <netinet/in.h>
    7 
    8 #include <sys/types.h>
    9 #include <sys/socket.h>
   10 
   11 #include <time.h>
   12 #include "bandwidthd.h"
   13 
   14 #ifdef HAVE_ARPA_NAMESER_H
   15 #include <arpa/nameser.h>
   16 #endif
   17 #ifdef HAVE_RESOLV_H
   18 #include <resolv.h>
   19 #endif
   20 
   21 extern unsigned int SubnetCount;
   22 extern struct config config;
   23 
   24 jmp_buf dnsjump;
   25 
   26 static void rdnslngjmp(int signal);
   27 
   28 void rdns(char *Buffer, unsigned long IP)  // This takes over sigalarm!
   29     {
   30 #ifdef HAVE_RESOLV_H
   31     char DNSError[] = "DNS Timeout: Correct to speed up graphing";
   32     char None[] = "Configure DNS to reverse this IP";
   33     char TooManyDNSTimeouts[] = "Too many dns timeouts, reverse lookups suspended";
   34     struct hostent *hostent;
   35     char chrIP[50];
   36     static int Init = TRUE;
   37     static int DNSTimeouts = 0;  // This is reset for each run because we're forked
   38     unsigned long addr = htonl(IP);
   39 
   40     _res.retrans = 1;
   41     _res.retry = 2;
   42 
   43     if (Init)
   44         {
   45         signal(SIGALRM, rdnslngjmp);
   46         Init = FALSE;
   47         }
   48 
   49     if (DNSTimeouts > 100)
   50         {
   51         syslog(LOG_ERR, "Too many dns timeouts, reverse lookups suspended");
   52         strncpy(Buffer, TooManyDNSTimeouts, 253);
   53         Buffer[254] = '\0';
   54         return;
   55         }       
   56 
   57     if (setjmp(dnsjump) == 0)
   58         {
   59         alarm(10);  // Don't let gethostbyaddr hold us up too long
   60         hostent = gethostbyaddr((char *) &addr, 4, AF_INET); // (char *)&Data->IP               
   61         alarm(0);
   62         
   63         if (hostent)
   64             sprintf(Buffer, "%s", hostent->h_name);
   65         else
   66             {
   67             strncpy(Buffer, None, 253);
   68             Buffer[254] = '\0';
   69             }
   70         }
   71     else  // Our alarm timed out
   72         {
   73         HostIp2CharIp(IP, chrIP);
   74         syslog(LOG_ERR, "DNS timeout for %s: This problem reduces graphing performance", chrIP);
   75         DNSTimeouts++;
   76         strncpy(Buffer, DNSError, 253);
   77         Buffer[254] = '\0';
   78         }
   79 #else
   80     Buffer[0] = '\0';
   81 #endif
   82     }
   83 
   84 static void rdnslngjmp(int signal)
   85     {
   86     longjmp(dnsjump, 1);
   87     }
   88 
   89 void swap(struct SummaryData **a, struct SummaryData **b) {
   90     struct SummaryData *temp;
   91     temp = *a; *a = *b; *b = temp;
   92 }
   93 void QuickSortSummaryData(struct SummaryData *SummaryData[], int left, int right) {
   94     int i,j,center;
   95     unsigned long long pivot;
   96     if (left==right) return;
   97     if (left+1==right) {
   98         if (SummaryData[left]->Total < SummaryData[right]->Total)
   99             swap(&SummaryData[left],&SummaryData[right]);
  100         return;
  101     }
  102     /* use the median-of-three method for picking pivot */
  103     center = (left+right)/2;
  104     if (SummaryData[left]->Total < SummaryData[center]->Total)
  105         swap(&SummaryData[left],&SummaryData[center]);
  106     if (SummaryData[left]->Total < SummaryData[right]->Total)
  107         swap(&SummaryData[left],&SummaryData[right]);
  108     if (SummaryData[center]->Total < SummaryData[right]->Total)
  109         swap(&SummaryData[center],&SummaryData[right]);
  110     pivot = SummaryData[center]->Total;
  111     swap(&SummaryData[center],&SummaryData[right-1]); /* hide the pivot */
  112     i = left; j = right - 1;
  113     do {
  114         do { ++i; } while (SummaryData[i]->Total > pivot);
  115         do { --j; } while (SummaryData[j]->Total < pivot);
  116         swap(&SummaryData[i],&SummaryData[j]);
  117     } while (j > i);
  118     swap(&SummaryData[i],&SummaryData[j]); /* undo last swap */
  119     swap(&SummaryData[i],&SummaryData[right-1]); /* restore pivot */
  120     QuickSortSummaryData(SummaryData,left,i-1);
  121     QuickSortSummaryData(SummaryData,i+1,right);
  122 }
  123 
  124 #define NumFactor 1024
  125 static void FormatNum(unsigned long long n, char *buf, int len) {
  126     double f;
  127     if (n<NumFactor) { snprintf(buf,len,"<td align=\"right\"><tt>%i&nbsp;</tt></td>",(int)n); return; }
  128     f = n;
  129     f /= NumFactor; if (f<NumFactor) { snprintf(buf,len,"<td align=\"right\"><tt>%.1fK</tt></td>",f); return; }
  130     f /= NumFactor; if (f<NumFactor) { snprintf(buf,len,"<td align=\"right\"><tt>%.1fM</tt></td>",f); return; }
  131     f /= NumFactor; if (f<NumFactor) { snprintf(buf,len,"<td align=\"right\"><tt>%.1fG</tt></td>",f); return; }
  132     f /= NumFactor; snprintf(buf,len,"<td align=\"right\"><tt>%.1fT</tt></td>\n",f);
  133 }
  134 
  135 void PrintTableLine(FILE *stream, struct SummaryData *Data, int Counter)
  136     {
  137     char Buffer1[50];
  138     char Buffer2[50];
  139     char Buffer3[50];
  140     char Buffer4[50];
  141     char Buffer4b[50];
  142     char Buffer5[50];
  143     char Buffer5b[50];
  144     char Buffer6[50];
  145     char Buffer7[50];
  146     char Buffer8[50];
  147 
  148     // First convert the info to nice, human readable stuff
  149     if (Data->IP == 0)
  150         strcpy(Buffer1, "Total");
  151     else
  152         HostIp2CharIp(Data->IP, Buffer1);
  153 
  154     FormatNum(Data->Total,         Buffer2,  50);
  155     FormatNum(Data->TotalSent,     Buffer3,  50);
  156     FormatNum(Data->TotalReceived, Buffer4,  50);
  157     FormatNum(Data->FTP,           Buffer4b, 50);
  158     FormatNum(Data->HTTP,          Buffer5,  50);
  159     FormatNum(Data->P2P,           Buffer5b, 50);
  160     FormatNum(Data->TCP,           Buffer6,  50);
  161     FormatNum(Data->UDP,           Buffer7,  50);
  162     FormatNum(Data->ICMP,          Buffer8,  50);
  163 
  164     if (Counter%4 == 0 || (Counter-1)%4 == 0)
  165         fprintf(stream, "<TR>");
  166     else
  167         fprintf(stream, "<TR bgcolor=lightblue>");
  168 
  169     if (Data->Graph)
  170         fprintf(stream, "<TD><a href=\"#%s-%c\">%s</a></TD>%s%s%s%s%s%s%s%s%s</TR>\n",
  171             Buffer1, // Ip
  172             config.tag,
  173             Buffer1, // Ip
  174             Buffer2, // Total
  175             Buffer3, // TotalSent
  176             Buffer4, // TotalReceived
  177             Buffer4b, // FTP
  178             Buffer5, // HTTP
  179             Buffer5b, // P2P
  180             Buffer6, // TCP
  181             Buffer7, // UDP
  182             Buffer8); // ICMP
  183     else
  184         fprintf(stream, "<TD>%s</TD>%s%s%s%s%s%s%s%s%s</TR>\n",
  185             Buffer1, // Ip
  186             Buffer2, // Total
  187             Buffer3, // TotalSent
  188             Buffer4, // TotalReceived
  189             Buffer4b, // FTP
  190             Buffer5, // HTTP
  191             Buffer5b, // P2P        
  192             Buffer6, // TCP
  193             Buffer7, // UDP
  194             Buffer8); // ICMP
  195     }
  196 
  197 void MakeIndexPages(int NumIps, struct SummaryData *SummaryData[])
  198     {
  199     int SubnetCounter;
  200     int Counter, tCounter;
  201     time_t WriteTime;
  202     char filename[] = "./htdocs/index2.html";
  203     char *PeriodDesc;
  204     
  205     FILE *file;
  206 
  207     char Buffer1[50];
  208     char Buffer2[50];
  209     char HostName[255];
  210 
  211     WriteTime = time(NULL);
  212     
  213     QuickSortSummaryData(SummaryData, 0, NumIps-1);
  214 
  215     ////////////////////////////////////////////////
  216     // Print main index page
  217     
  218     if (config.tag == '1')
  219         {
  220         if ((file = fopen("./htdocs/index.html", "wt")) == NULL)
  221             {
  222             syslog(LOG_ERR, "Failed to open ./htdocs/index.html");
  223             exit(1);
  224             }
  225         }
  226     else
  227         {
  228         filename[14] = config.tag;
  229         if ((file = fopen(filename, "wt")) == NULL)
  230             {
  231             syslog(LOG_ERR, "Failed to open %s", filename);
  232             exit(1);
  233             }
  234         }
  235 
  236     switch (config.tag)
  237         {
  238         case '1': PeriodDesc = "Daily"; break;
  239         case '2': PeriodDesc = "Weekly"; break;
  240         case '3': PeriodDesc = "Monthly"; break;
  241         case '4': PeriodDesc = "Yearly"; break;
  242         default: PeriodDesc = ""; break;
  243         }
  244     
  245     fprintf(file, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
  246     fprintf(file, "<HTML>\n<HEAD>\n<TITLE>Bandwidthd</TITLE>\n");
  247 
  248     if (config.meta_refresh)
  249         fprintf(file, "<META HTTP-EQUIV=\"REFRESH\" content=\"%u\">\n",
  250                 config.meta_refresh);
  251     fprintf(file, "<META HTTP-EQUIV=\"EXPIRES\" content=\"-1\">\n");
  252     fprintf(file, "<META HTTP-EQUIV=\"PRAGMA\" content=\"no-cache\">\n");
  253     fprintf(file, "</HEAD>\n<BODY vlink=blue>\n%s<br>\n<center><img src=\"logo.gif\" ALT=\"Logo\"><BR>\n", ctime(&WriteTime));
  254     fprintf(file, "Programmed by David Hinkle, Commissioned by <a href=\"http://www.derbytech.com\">DerbyTech</a> wireless networking.<BR>");
  255     fprintf(file, "<BR>\n - <a href=\"index.html\">Daily</a> -- <a href=\"index2.html\">Weekly</a> -- ");
  256     fprintf(file, "<a href=\"index3.html\">Monthly</a> -- <a href=\"index4.html\">Yearly</a> - <BR>\n");
  257 
  258     fprintf(file, "<BR>\nPick a Subnet:<BR>\n");    
  259     if (config.tag == '1')
  260         fprintf(file, "- <a href=\"index.html\">Top20</a> -");
  261     else
  262         fprintf(file, "- <a href=\"index%c.html\">Top20</a> -", config.tag);
  263 
  264     for (Counter = 0; Counter < SubnetCount; Counter++)            
  265         {
  266         HostIp2CharIp(SubnetTable[Counter].ip, Buffer1);
  267         fprintf(file, "- <a href=\"Subnet-%c-%s.html\">%s</a> -", config.tag, Buffer1, Buffer1);
  268         }
  269 
  270     /////  TOP 20
  271 
  272     fprintf(file, "<H1>Top 20 IPs by Traffic - %s</H1></center>", PeriodDesc);
  273     fprintf(file, "<center>\n<table width=\"100%%\" border=1 cellspacing=0>\n");
  274 
  275     // PASS 1:  Write out the table
  276 
  277     fprintf(file, "<TR bgcolor=lightblue><TD>Ip and Name<TD align=center>Total<TD align=center>Total Sent<TD align=center>Total Received<TD align=center>FTP<TD align=center>HTTP<TD align=center>P2P<TD align=center>TCP<TD align=center>UDP<TD align=center>ICMP\n");
  278     for (Counter=0; Counter < 21 && Counter < NumIps; Counter++)
  279         PrintTableLine(file, SummaryData[Counter], Counter);
  280 
  281     fprintf(file, "</table></center>\n");
  282 
  283     // PASS 2: The graphs
  284     for (Counter=0; Counter < 21 && Counter < NumIps; Counter++)
  285         if (SummaryData[Counter]->Graph)
  286             {
  287             if (SummaryData[Counter]->IP == 0)
  288                 {
  289                 strcpy(Buffer1, "Total");   
  290                 strcpy(HostName, "Total of all subnets");
  291                 }
  292             else
  293                 {   
  294                 HostIp2CharIp(SummaryData[Counter]->IP, Buffer1);
  295                 rdns(HostName, SummaryData[Counter]->IP);
  296                 }
  297             fprintf(file, "<a name=\"%s-%c\"></a><H1><a href=\"#top\">(Top)</a> %s - %s</H1><BR>\nSend:<br>\n<img src=%s-%c-S.png ALT=\"Sent traffic for %s\"><BR>\n<img src=legend.gif ALT=\"Legend\"><br>\nReceived:<br>\n<img src=%s-%c-R.png ALT=\"Sent traffic for %s\"><BR>\n<img src=legend.gif ALT=\"Legend\"><br>\n<BR>\n", Buffer1, config.tag, Buffer1, HostName, Buffer1, config.tag, Buffer1, Buffer1, config.tag, Buffer1);
  298             }
  299 
  300     fprintf(file, "</BODY></HTML>\n");
  301 
  302     fclose(file);
  303 
  304     ////////////////////////////////////////////////
  305     // Print each subnet page
  306 
  307     for (SubnetCounter = 0; SubnetCounter < SubnetCount; SubnetCounter++)
  308         {
  309         HostIp2CharIp(SubnetTable[SubnetCounter].ip, Buffer1);
  310         sprintf(Buffer2, "./htdocs/Subnet-%c-%s.html", config.tag, Buffer1);
  311         file = fopen(Buffer2, "wt");
  312         fprintf(file, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
  313         fprintf(file, "<HTML>\n<HEAD><TITLE>Bandwidthd - Subnet %s</TITLE>\n", Buffer1);
  314 
  315         if (config.meta_refresh)
  316             fprintf(file, "<META HTTP-EQUIV=\"REFRESH\" content=\"%u\">\n",
  317                     config.meta_refresh);
  318         fprintf(file, "<META HTTP-EQUIV=\"EXPIRES\" content=\"-1\">\n");
  319         fprintf(file, "<META HTTP-EQUIV=\"PRAGMA\" content=\"no-cache\">\n");
  320         fprintf(file, "</HEAD>\n<BODY vlink=blue>\n%s<br>\n<CENTER><a name=\"Top\"></a>", ctime(&WriteTime));
  321         fprintf(file, "<img src=\"logo.gif\" ALT=\"Logo\"><BR>");
  322         fprintf(file, "Programmed by David Hinkle, Commissioned by <a href=\"http://www.derbytech.com\">DerbyTech</a> wireless networking.<BR>\n");
  323 
  324         fprintf(file, "<BR>\n - <a href=\"index.html\">Daily</a> -- <a href=\"index2.html\">Weekly</a> -- ");
  325         fprintf(file, "<a href=\"index3.html\">Monthly</a> -- <a href=\"index4.html\">Yearly</a> - <BR>\n");
  326 
  327         fprintf(file, "<BR>\nPick a Subnet:<BR>\n");
  328         if (config.tag == '1')
  329             fprintf(file, "- <a href=\"index.html\">Top20</a> -");
  330         else
  331             fprintf(file, "- <a href=\"index%c.html\">Top20</a> -", config.tag);
  332 
  333         for (Counter = 0; Counter < SubnetCount; Counter++)
  334             {
  335             HostIp2CharIp(SubnetTable[Counter].ip, Buffer2);
  336             fprintf(file, "- <a href=\"Subnet-%c-%s.html\">%s</a> -", config.tag, Buffer2, Buffer2);
  337             }
  338 
  339         fprintf(file, "<H1>%s - %s</H1></center>", Buffer1, PeriodDesc);
  340         fprintf(file, "<table width=\"100%%\" border=1 cellspacing=0>\n");
  341 
  342         // PASS 1:  Write out the table
  343 
  344         fprintf(file, "<TR bgcolor=lightblue><TD>Ip and Name<TD align=center>Total<TD align=center>Total Sent<TD align=center>Total Received<TD align=center>FTP<TD align=center>HTTP<TD align=center>P2P<TD align=center>TCP<TD align=center>UDP<TD align=center>ICMP\n");
  345         for (tCounter=0, Counter=0; Counter < NumIps; Counter++)
  346             {
  347             if (SubnetTable[SubnetCounter].ip == (SummaryData[Counter]->IP & SubnetTable[SubnetCounter].mask))
  348                 { // The ip belongs to this subnet
  349                 PrintTableLine(file, SummaryData[Counter], tCounter++);
  350                 }
  351             }
  352 
  353         fprintf(file, "</table>\n");
  354 
  355         // PASS 2: The graphs
  356         for (Counter=0; Counter < NumIps; Counter++)
  357             {
  358             if (SubnetTable[SubnetCounter].ip == (SummaryData[Counter]->IP & SubnetTable[SubnetCounter].mask))
  359                 { // The ip belongs to this subnet
  360                 if (SummaryData[Counter]->Graph)
  361                     {
  362                     HostIp2CharIp(SummaryData[Counter]->IP, Buffer1);
  363                     rdns(HostName, SummaryData[Counter]->IP);
  364                     fprintf(file, "<a name=\"%s-%c\"></a><H1><a href=\"#top\">(Top)</a> %s - %s</H1><BR>\nSend:<br>\n<img src=%s-%c-S.png ALT=\"Sent traffic graph for %s\"><BR>\n<img src=legend.gif ALT=\"Legend\"><br>\nReceived:<br>\n<img src=%s-%c-R.png ALT=\"Received traffic for %s\"><BR>\n<img src=legend.gif ALT=\"Legend\"><br>\n<BR>\n", Buffer1, config.tag, Buffer1, HostName, Buffer1, config.tag, Buffer1, Buffer1, config.tag, Buffer1);
  365                     }
  366                 }
  367             }
  368 
  369         fprintf(file, "</BODY></HTML>\n");
  370         fclose(file);
  371         }
  372 
  373     free(SummaryData);
  374     }
  375 
  376 void GraphIp(struct IPDataStore *DataStore, struct SummaryData *SummaryData, time_t timestamp)
  377     {
  378     FILE *OutputFile;
  379     char outputfilename[50];
  380     gdImagePtr im, im2;
  381     int white;
  382     unsigned long long int YMax;
  383     char CharIp[20];
  384 
  385     time_t GraphBeginTime;
  386 
  387     // TODO: First determine if graph will be printed before creating image and drawing backround, etc
  388 
  389     if (DataStore->ip == 0)
  390         strcpy(CharIp, "Total");
  391     else
  392         HostIp2CharIp(DataStore->ip, CharIp);
  393 
  394     GraphBeginTime = timestamp - config.range;
  395 
  396     im = gdImageCreate(XWIDTH, YHEIGHT);
  397     white = gdImageColorAllocate(im, 255, 255, 255);
  398     //gdImageFill(im, 10, 10, white);
  399 
  400     im2 = gdImageCreate(XWIDTH, YHEIGHT);
  401     white = gdImageColorAllocate(im2, 255, 255, 255);
  402     //gdImageFill(im2, 10, 10, white);
  403 
  404     YMax = GraphData(im, im2, DataStore, GraphBeginTime, SummaryData);
  405     if (YMax != 0)
  406         {
  407         // Finish the graph
  408         PrepareXAxis(im, timestamp);
  409         PrepareYAxis(im, YMax);
  410 
  411         PrepareXAxis(im2, timestamp);
  412         PrepareYAxis(im2, YMax);
  413 
  414         sprintf(outputfilename, "./htdocs/%s-%c-S.png", CharIp, config.tag);
  415         OutputFile = fopen(outputfilename, "wb");    
  416         gdImagePng(im, OutputFile);
  417         fclose(OutputFile);
  418 
  419         sprintf(outputfilename, "./htdocs/%s-%c-R.png", CharIp, config.tag);
  420         OutputFile = fopen(outputfilename, "wb");
  421         gdImagePng(im2, OutputFile);
  422         fclose(OutputFile);
  423         }
  424     else
  425         {
  426         // The graph isn't worth clutering up the web pages with
  427         sprintf(outputfilename, "./htdocs/%s-%c-R.png", CharIp, config.tag);
  428         unlink(outputfilename);
  429         sprintf(outputfilename, "./htdocs/%s-%c-S.png", CharIp, config.tag);
  430         unlink(outputfilename);
  431         }
  432 
  433     gdImageDestroy(im);
  434     gdImageDestroy(im2);
  435     }
  436 
  437 // Returns YMax
  438 unsigned long long int GraphData(gdImagePtr im, gdImagePtr im2, struct IPDataStore *DataStore, time_t timestamp, struct SummaryData *SummaryData)
  439     {
  440     unsigned long long int YMax=0;
  441     
  442     struct DataStoreBlock *CurrentBlock;
  443     struct IPData *Data;
  444 
  445     // TODO: These should be a structure!!!!
  446     // TODO: This is an awfull lot of data to be allocated on the stack
  447 
  448     unsigned long long total[XWIDTH];
  449     unsigned long long icmp[XWIDTH];
  450     unsigned long long udp[XWIDTH];
  451     unsigned long long tcp[XWIDTH];
  452     unsigned long long ftp[XWIDTH];
  453     unsigned long long http[XWIDTH];
  454     unsigned long long p2p[XWIDTH];
  455     int Count[XWIDTH];
  456 
  457     unsigned long long total2[XWIDTH];
  458     unsigned long long icmp2[XWIDTH];
  459     unsigned long long udp2[XWIDTH];
  460     unsigned long long tcp2[XWIDTH];
  461     unsigned long long ftp2[XWIDTH];
  462     unsigned long long http2[XWIDTH];
  463     unsigned long long p2p2[XWIDTH];
  464 
  465     size_t DataPoints;
  466     double x;
  467     int xint;
  468     int Counter;
  469     char Buffer[30];
  470     char Buffer2[50];
  471     
  472     int blue, lblue, red, yellow, purple, green, brown, black;
  473     int blue2, lblue2, red2, yellow2, purple2, green2, brown2, black2;
  474 
  475     unsigned long long int SentPeak = 0;
  476     unsigned long long int ReceivedPeak = 0;
  477 
  478     yellow   = gdImageColorAllocate(im, 255, 255, 0);
  479     purple   = gdImageColorAllocate(im, 255, 0, 255);
  480     green    = gdImageColorAllocate(im, 0, 255, 0);
  481     blue     = gdImageColorAllocate(im, 0, 0, 255);
  482     lblue    = gdImageColorAllocate(im, 128, 128, 255);
  483     brown    = gdImageColorAllocate(im, 128, 0, 0);
  484     red      = gdImageColorAllocate(im, 255, 0, 0);
  485     black    = gdImageColorAllocate(im, 0, 0, 0);
  486     
  487     yellow2  = gdImageColorAllocate(im2, 255, 255, 0);
  488     purple2   = gdImageColorAllocate(im2, 255, 0, 255);
  489     green2   = gdImageColorAllocate(im2, 0, 255, 0);
  490     blue2    = gdImageColorAllocate(im2, 0, 0, 255);
  491     lblue2   = gdImageColorAllocate(im2, 128, 128, 255);
  492     brown2   = gdImageColorAllocate(im2, 128, 0, 0);
  493     red2     = gdImageColorAllocate(im2, 255, 0, 0);
  494     black2   = gdImageColorAllocate(im2, 0, 0, 0);
  495 
  496     CurrentBlock = DataStore->FirstBlock;
  497     Data = CurrentBlock->Data;
  498     DataPoints = CurrentBlock->NumEntries;
  499 
  500     memset(SummaryData, 0, sizeof(struct SummaryData));
  501     SummaryData->IP = Data[0].ip;
  502     
  503     memset(Count, 0, sizeof(Count[0])*XWIDTH);
  504 
  505     memset(total, 0, sizeof(total[0])*XWIDTH);
  506     memset(icmp, 0, sizeof(total[0])*XWIDTH);
  507     memset(udp, 0, sizeof(total[0])*XWIDTH);
  508     memset(tcp, 0, sizeof(total[0])*XWIDTH);
  509     memset(ftp, 0, sizeof(total[0])*XWIDTH);
  510     memset(http, 0, sizeof(total[0])*XWIDTH);
  511     memset(p2p, 0, sizeof(total[0])*XWIDTH);
  512 
  513     memset(total2, 0, sizeof(total[0])*XWIDTH);
  514     memset(icmp2, 0, sizeof(total[0])*XWIDTH);
  515     memset(udp2, 0, sizeof(total[0])*XWIDTH);
  516     memset(tcp2, 0, sizeof(total[0])*XWIDTH);
  517     memset(ftp2, 0, sizeof(total[0])*XWIDTH);
  518     memset(http2, 0, sizeof(total[0])*XWIDTH);
  519     memset(p2p2, 0, sizeof(total[0])*XWIDTH);
  520 
  521     // Change this to just run through all the datapoints we have stored in ram
  522 
  523     // Sum up the bytes/second
  524     while(DataPoints > 0)  // We have data to graph
  525         {
  526         for (Counter = 0; Counter < DataPoints; Counter++)  // Graph it all
  527             {
  528             x = (Data[Counter].timestamp-timestamp)*((XWIDTH-XOFFSET)/config.range)+XOFFSET;        
  529             xint = x;
  530 
  531             if (xint >= 0 && xint < XWIDTH)
  532                 {
  533                 Count[xint]++;
  534                 
  535                 if (Data[Counter].Send.total > SentPeak)
  536                     SentPeak = Data[Counter].Send.total;
  537                 total[xint] += Data[Counter].Send.total;
  538                 icmp[xint] += Data[Counter].Send.icmp;
  539                 udp[xint] += Data[Counter].Send.udp;
  540                 tcp[xint] += Data[Counter].Send.tcp;
  541                 ftp[xint] += Data[Counter].Send.ftp;
  542                 http[xint] += Data[Counter].Send.http;
  543                 p2p[xint] += Data[Counter].Send.p2p;
  544 
  545                 if (Data[Counter].Receive.total > ReceivedPeak)
  546                     ReceivedPeak = Data[Counter].Receive.total;
  547                 total2[xint] += Data[Counter].Receive.total;
  548                 icmp2[xint] += Data[Counter].Receive.icmp;
  549                 udp2[xint] += Data[Counter].Receive.udp;
  550                 tcp2[xint] += Data[Counter].Receive.tcp;
  551                 ftp2[xint] += Data[Counter].Receive.ftp;
  552                 http2[xint] += Data[Counter].Receive.http;
  553                 p2p2[xint] += Data[Counter].Receive.p2p;
  554                 }
  555             }
  556 
  557         CurrentBlock = CurrentBlock->Next;
  558             
  559         if (CurrentBlock)
  560             {
  561             Data = CurrentBlock->Data;
  562             DataPoints = CurrentBlock->NumEntries;
  563             }
  564         else
  565             DataPoints = 0;     
  566         }
  567 
  568     // Convert SentPeak and ReceivedPeak from bytes to bytes/second
  569     SentPeak /= config.interval; ReceivedPeak /= config.interval;
  570 
  571     // Preform the Average
  572     for(Counter=XOFFSET+1; Counter < XWIDTH; Counter++)
  573             {
  574             if (Count[Counter] > 0)
  575                 {
  576                 SummaryData->Total += total[Counter] + total2[Counter];
  577                 SummaryData->TotalSent += total[Counter];
  578                 SummaryData->TotalReceived += total2[Counter];
  579                 SummaryData->TCP += tcp[Counter] + tcp2[Counter];
  580                 SummaryData->FTP += ftp[Counter] + ftp2[Counter];
  581                 SummaryData->HTTP += http[Counter] + http2[Counter];
  582                 SummaryData->P2P += p2p[Counter] + p2p2[Counter];
  583                 SummaryData->UDP += udp[Counter] + udp2[Counter];
  584                 SummaryData->ICMP += icmp[Counter] + icmp2[Counter];
  585 
  586                 // Preform the average
  587                 total[Counter] /= (Count[Counter]*config.interval);
  588                 tcp[Counter] /= (Count[Counter]*config.interval);
  589                 ftp[Counter] /= (Count[Counter]*config.interval);
  590                 http[Counter] /= (Count[Counter]*config.interval);
  591                 p2p[Counter] /= (Count[Counter]*config.interval);
  592                 udp[Counter] /= (Count[Counter]*config.interval);
  593                 icmp[Counter] /= (Count[Counter]*config.interval);
  594                                 
  595                 total2[Counter] /= (Count[Counter]*config.interval);
  596                 tcp2[Counter] /= (Count[Counter]*config.interval);
  597                 ftp2[Counter] /= (Count[Counter]*config.interval);
  598                 http2[Counter] /= (Count[Counter]*config.interval);
  599                 p2p2[Counter] /= (Count[Counter]*config.interval);
  600                 udp2[Counter] /= (Count[Counter]*config.interval);
  601                 icmp2[Counter] /= (Count[Counter]*config.interval);
  602 
  603 
  604                 if (total[Counter] > YMax)
  605                     YMax = total[Counter];
  606                 
  607                 if (total2[Counter] > YMax)
  608                     YMax = total2[Counter];
  609                 }
  610             }
  611 
  612     YMax += YMax*0.05;    // Add an extra 5%
  613     
  614     if ((SummaryData->IP != 0 && SummaryData->Total < config.graph_cutoff))
  615         {
  616         SummaryData->Graph = FALSE;
  617         return(0);
  618         }
  619     else
  620         SummaryData->Graph = TRUE;
  621 
  622     // Plot the points
  623     for(Counter=XOFFSET+1; Counter < XWIDTH; Counter++)    
  624             {
  625             if (Count[Counter] > 0)
  626                 {
  627                 // Convert the bytes/sec to y coords
  628                 total[Counter] = (total[Counter]*(YHEIGHT-YOFFSET))/YMax;
  629                 tcp[Counter] = (tcp[Counter]*(YHEIGHT-YOFFSET))/YMax;
  630                 ftp[Counter] = (ftp[Counter]*(YHEIGHT-YOFFSET))/YMax;
  631                 http[Counter] = (http[Counter]*(YHEIGHT-YOFFSET))/YMax;
  632                 p2p[Counter] = (p2p[Counter]*(YHEIGHT-YOFFSET))/YMax;
  633                 udp[Counter] = (udp[Counter]*(YHEIGHT-YOFFSET))/YMax;
  634                 icmp[Counter] = (icmp[Counter]*(YHEIGHT-YOFFSET))/YMax;
  635 
  636                 total2[Counter] = (total2[Counter]*(YHEIGHT-YOFFSET))/YMax;
  637                 tcp2[Counter] = (tcp2[Counter]*(YHEIGHT-YOFFSET))/YMax;
  638                 ftp2[Counter] = (ftp2[Counter]*(YHEIGHT-YOFFSET))/YMax;
  639                 http2[Counter] = (http2[Counter]*(YHEIGHT-YOFFSET))/YMax;
  640                 p2p2[Counter] = (p2p2[Counter]*(YHEIGHT-YOFFSET))/YMax;
  641                 udp2[Counter] = (udp2[Counter]*(YHEIGHT-YOFFSET))/YMax;
  642                 icmp2[Counter] = (icmp2[Counter]*(YHEIGHT-YOFFSET))/YMax;
  643 
  644                 // Stack 'em up!
  645                 // Total is stacked from the bottom
  646                 // Icmp is on the bottom too
  647                 // Udp is stacked on top of icmp
  648                 udp[Counter] += icmp[Counter];
  649                 udp2[Counter] += icmp2[Counter];
  650                 // TCP and p2p are stacked on top of Udp
  651                 tcp[Counter] += udp[Counter];
  652                 tcp2[Counter] += udp2[Counter];
  653                 p2p[Counter] += udp[Counter];
  654                 p2p2[Counter] += udp2[Counter];
  655                 // Http is stacked on top of p2p
  656                 http[Counter] += p2p[Counter];
  657                 http2[Counter] += p2p2[Counter];
  658                 // Ftp is stacked on top of http
  659                 ftp[Counter] += http[Counter];
  660                 ftp2[Counter] += http2[Counter];
  661 
  662                 // Plot them!
  663                 // Sent
  664                 gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - total[Counter], Counter, YHEIGHT-YOFFSET-1, yellow);
  665                 gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - icmp[Counter], Counter, YHEIGHT-YOFFSET-1, red);
  666                 gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - udp[Counter], Counter, (YHEIGHT-YOFFSET) - icmp[Counter] - 1, brown);
  667                 gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - tcp[Counter], Counter, (YHEIGHT-YOFFSET) - udp[Counter] - 1, green);
  668                 gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - p2p[Counter], Counter, (YHEIGHT-YOFFSET) - udp[Counter] - 1, purple);
  669                 gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - http[Counter], Counter, (YHEIGHT-YOFFSET) - p2p[Counter] - 1, blue);
  670                 gdImageLine(im, Counter, (YHEIGHT-YOFFSET) - ftp[Counter], Counter, (YHEIGHT-YOFFSET) - http[Counter] - 1, lblue);
  671                                 
  672                 // Receive
  673                 gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - total2[Counter], Counter, YHEIGHT-YOFFSET-1, yellow2);
  674                 gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - icmp2[Counter], Counter, YHEIGHT-YOFFSET-1, red2);
  675                 gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - udp2[Counter], Counter, (YHEIGHT-YOFFSET) - icmp2[Counter] - 1, brown2);
  676                 gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - tcp2[Counter], Counter, (YHEIGHT-YOFFSET) - udp2[Counter] - 1, green2);
  677                 gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - p2p2[Counter], Counter, (YHEIGHT-YOFFSET) - udp2[Counter] - 1, purple2);
  678                 gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - http2[Counter], Counter, (YHEIGHT-YOFFSET) - p2p2[Counter] - 1, blue2);
  679                 gdImageLine(im2, Counter, (YHEIGHT-YOFFSET) - ftp2[Counter], Counter, (YHEIGHT-YOFFSET) - http2[Counter] - 1, lblue2);
  680 
  681 
  682                 }
  683             }
  684 
  685     if (SentPeak < 1024/8)
  686         snprintf(Buffer2, 50, "Peak Send Rate: %.1f Bits/sec", (double)SentPeak*8);
  687     else if (SentPeak < (1024*1024)/8)
  688         snprintf(Buffer2, 50, "Peak Send Rate: %.1f KBits/sec", ((double)SentPeak*8.0)/1024.0);
  689     else snprintf(Buffer2, 50, "Peak Send Rate: %.1f MBits/sec", ((double)SentPeak*8.0)/(1024.0*1024.0));
  690                                 
  691     if (SummaryData->TotalSent < 1024)
  692         snprintf(Buffer, 30, "Sent %.1f Bytes", (double)SummaryData->TotalSent);                    
  693     else if (SummaryData->TotalSent < 1024*1024)
  694         snprintf(Buffer, 30, "Sent %.1f KBytes", (double)SummaryData->TotalSent/1024.0);
  695     else snprintf(Buffer, 30, "Sent %.1f MBytes", (double)SummaryData->TotalSent/(1024.0*1024.0));
  696 
  697     gdImageString(im, gdFontSmall, XOFFSET+5,  YHEIGHT-20, Buffer, black);
  698     gdImageString(im, gdFontSmall, XWIDTH/2+XOFFSET/2,  YHEIGHT-20, Buffer2, black);                
  699 
  700     if (ReceivedPeak < 1024/8)
  701         snprintf(Buffer2, 50, "Peak Receive Rate: %.1f Bits/sec", (double)ReceivedPeak*8);
  702     else if (ReceivedPeak < (1024*1024)/8)
  703         snprintf(Buffer2, 50, "Peak Receive Rate: %.1f KBits/sec", ((double)ReceivedPeak*8.0)/1024.0);               
  704     else snprintf(Buffer2, 50, "Peak Receive Rate: %.1f MBits/sec", ((double)ReceivedPeak*8.0)/(1024.0*1024.0));
  705 
  706     if (SummaryData->TotalReceived < 1024)
  707         snprintf(Buffer, 30, "Received %.1f Bytes", (double)SummaryData->TotalReceived);
  708     else if (SummaryData->TotalReceived < 1024*1024)
  709         snprintf(Buffer, 30, "Received %.1f KBytes", (double)SummaryData->TotalReceived/1024.0);
  710     else snprintf(Buffer, 30, "Received %.1f MBytes", (double)SummaryData->TotalReceived/(1024.0*1024.0));
  711                                                                                                               
  712     gdImageString(im2, gdFontSmall, XOFFSET+5,  YHEIGHT-20, Buffer, black2);                
  713     gdImageString(im2, gdFontSmall, XWIDTH/2+XOFFSET/2,  YHEIGHT-20, Buffer2, black2);
  714 
  715     return(YMax);
  716     }
  717 
  718 void PrepareYAxis(gdImagePtr im, unsigned long long int YMax)
  719     {
  720     char buffer[20];
  721 
  722     char YLegend;
  723     long long int Divisor;
  724 
  725     int black;
  726     float YTic = 0;
  727     double y;
  728     long int YStep;
  729     
  730     black = gdImageColorAllocate(im, 0, 0, 0);
  731     gdImageLine(im, XOFFSET, 0, XOFFSET, YHEIGHT, black);
  732 
  733     YLegend = ' ';
  734     Divisor = 1;
  735     if (YMax*8 > 1024*2)
  736         {
  737         Divisor = 1024;    // Display in K
  738         YLegend = 'k';
  739         }
  740     if (YMax*8 > 1024*1024*2)
  741         {
  742         Divisor = 1024*1024; // Display in M
  743         YLegend = 'm';
  744         }
  745     if (YMax*8 > (long long)1024*1024*1024*2)
  746         {
  747         Divisor = 1024*1024*1024; // Display in G
  748         YLegend = 'g';
  749         }
  750 
  751     YStep = YMax/10;
  752     if (YStep < 1)
  753         YStep=1;
  754     YTic=YStep;
  755 
  756     while (YTic < (YMax - YMax/10))
  757         {
  758         y = (YHEIGHT-YOFFSET)-((YTic*(YHEIGHT-YOFFSET))/YMax);        
  759 
  760         gdImageLine(im, XOFFSET, y, XWIDTH, y, black);        
  761         snprintf(buffer, 20, "%4.1f %cbits/s", (float)(8.0*YTic)/Divisor, YLegend);
  762         gdImageString(im, gdFontSmall, 3, y-7, buffer, black);        
  763 
  764         YTic += YStep;
  765         }
  766     } 
  767 
  768 void PrepareXAxis(gdImagePtr im, time_t timestamp)
  769     {
  770     char buffer[100];
  771     int black, red;
  772     time_t sample_begin, sample_end;    
  773     struct tm *timestruct;
  774     long int MarkTime;
  775     long int MarkTimeStep;
  776     double x;
  777     
  778     sample_begin=timestamp-config.range;
  779     sample_end=sample_begin+config.interval;
  780 
  781     black = gdImageColorAllocate(im, 0, 0, 0);
  782     red   = gdImageColorAllocate(im, 255, 0, 0);
  783 
  784     gdImageLine(im, 0, YHEIGHT-YOFFSET, XWIDTH, YHEIGHT-YOFFSET, black);
  785 
  786     // ********************************************************************
  787     // ****  Write the red day/month seperator bars
  788     // ********************************************************************
  789 
  790     if ((24*60*60*(XWIDTH-XOFFSET))/config.range > (XWIDTH-XOFFSET)/10)
  791         {
  792         // Day bars
  793         timestruct = localtime((time_t *)&sample_begin);
  794         timestruct->tm_sec = 0;
  795         timestruct->tm_min = 0;
  796         timestruct->tm_hour = 0;
  797         MarkTime = mktime(timestruct);
  798             
  799         x = (MarkTime-sample_begin)*( ((double)(XWIDTH-XOFFSET)) / config.range) + XOFFSET;
  800         while (x < XOFFSET)
  801             {
  802             MarkTime += (24*60*60);
  803             x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET;
  804             }
  805 
  806         while (x < (XWIDTH-10))
  807             {
  808             // Day Lines
  809             gdImageLine(im, x, 0, x, YHEIGHT-YOFFSET, red);
  810             gdImageLine(im, x+1, 0, x+1, YHEIGHT-YOFFSET, red);
  811     
  812             timestruct = localtime((time_t *)&MarkTime);
  813             strftime(buffer, 100, "%a, %b %d", timestruct);
  814             gdImageString(im, gdFontSmall, x-30,  YHEIGHT-YOFFSET+10, buffer, black);        
  815 
  816             // Calculate Next x
  817             MarkTime += (24*60*60);
  818             x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET;
  819             }
  820         }
  821     else
  822         {
  823         // Month Bars
  824         timestruct = localtime((time_t *)&sample_begin);
  825         timestruct->tm_sec = 0;
  826         timestruct->tm_min = 0;
  827         timestruct->tm_hour = 0;
  828         timestruct->tm_mday = 1;
  829         timestruct->tm_mon--; // Start the month before the sample
  830         MarkTime = mktime(timestruct);
  831 
  832         x = (MarkTime-sample_begin)*( ((double)(XWIDTH-XOFFSET)) / config.range) + XOFFSET;
  833         while (x < XOFFSET)
  834             {
  835             timestruct->tm_mon++;
  836             MarkTime = mktime(timestruct);
  837             x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET;
  838             }
  839 
  840         while (x < (XWIDTH-10))
  841             {
  842             // Month Lines
  843             gdImageLine(im, x, 0, x, YHEIGHT-YOFFSET, red);
  844             gdImageLine(im, x+1, 0, x+1, YHEIGHT-YOFFSET, red);
  845     
  846             timestruct = localtime((time_t *)&MarkTime);
  847             strftime(buffer, 100, "%b", timestruct);
  848             gdImageString(im, gdFontSmall, x-6,  YHEIGHT-YOFFSET+10, buffer, black);        
  849 
  850             // Calculate Next x
  851             timestruct->tm_mon++;
  852             MarkTime = mktime(timestruct);
  853             x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET;
  854             }               
  855         }
  856 
  857     // ********************************************************************
  858     // ****  Write the tic marks
  859     // ********************************************************************
  860 
  861     timestruct = localtime((time_t *)&sample_begin);
  862     timestruct->tm_sec = 0;
  863     timestruct->tm_min = 0;
  864     timestruct->tm_hour = 0;
  865     MarkTime = mktime(timestruct);
  866 
  867     if ((6*60*60*(XWIDTH-XOFFSET))/config.range > 10) // pixels per 6 hours is more than 2
  868         MarkTimeStep = 6*60*60; // Major ticks are 6 hours
  869     else if ((24*60*60*(XWIDTH-XOFFSET))/config.range > 10)
  870         MarkTimeStep = 24*60*60; // Major ticks are 24 hours;
  871     else
  872         return; // Done     
  873 
  874     x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET;
  875     while (x < XOFFSET)
  876         {
  877         MarkTime += MarkTimeStep;
  878         x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET;
  879         }
  880 
  881     while (x < (XWIDTH-10))
  882         {
  883         if (x > XOFFSET) {
  884             gdImageLine(im, x, YHEIGHT-YOFFSET-5, x, YHEIGHT-YOFFSET+5, black);
  885             gdImageLine(im, x+1, YHEIGHT-YOFFSET-5, x+1, YHEIGHT-YOFFSET+5, black);
  886             }
  887         MarkTime += MarkTimeStep;
  888         x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET;
  889         }
  890 
  891     timestruct = localtime((time_t *)&sample_begin);
  892     timestruct->tm_sec = 0;
  893     timestruct->tm_min = 0;
  894     timestruct->tm_hour = 0;
  895     MarkTime = mktime(timestruct);
  896 
  897     if ((60*60*(XWIDTH-XOFFSET))/config.range > 2) // pixels per hour is more than 2
  898         MarkTimeStep = 60*60;  // Minor ticks are 1 hour
  899     else if ((6*60*60*(XWIDTH-XOFFSET))/config.range > 2)
  900         MarkTimeStep = 6*60*60; // Minor ticks are 6 hours
  901     else if ((24*60*60*(XWIDTH-XOFFSET))/config.range > 2)
  902         MarkTimeStep = 24*60*60;
  903     else
  904         return; // Done
  905 
  906     // Draw Minor Tic Marks
  907     x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET;
  908 
  909     while (x < XOFFSET)
  910         {
  911         MarkTime += MarkTimeStep;
  912         x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET;
  913         }
  914 
  915     while (x < (XWIDTH-10))
  916         {
  917         if (x > XOFFSET) {
  918             gdImageLine(im, x, YHEIGHT-YOFFSET, x, YHEIGHT-YOFFSET+5, black);
  919             gdImageLine(im, x+1, YHEIGHT-YOFFSET, x+1, YHEIGHT-YOFFSET+5, black);
  920             }
  921         MarkTime+=MarkTimeStep;
  922         x = (MarkTime-sample_begin)*((XWIDTH-XOFFSET)/config.range) + XOFFSET;
  923         }
  924     }
  925 
  926