/*
 * $Id: proc_net_dev.c,v 1.1 2001/03/15 22:16:13 jpormann Exp jpormann $
 *
 * procstatd - Copyright (c) 1999 by Robert G. Brown, rgb@phy.duke.edu
 *         GPL version 2b (b for beverage) granted.
 *
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * procstatd - A daemon to extract statistics from /proc/stat and publish them
 *         on demand via a socket connection or broadcast.
 */

#include "procstatd.h"

void init_proc_net_dev()
{

 int i,numfields;

 /* 
  * Open /proc/stat.
  */
 stat_fd[PROC_NET_DEV] = fopen("/proc/net/dev","r");

 /*
  * If the open succeeded, the file descriptor is nonzero.  We then
  * initialize all stats derived from /proc/stat.  Put values into
  * stats[FIELD].{name,source,avail,current,previous,rate}
  */
 /* /proc/net/dev */
 if(stat_fd[PROC_NET_DEV]){
   while(TRUE){
     /* Normal EOF causes break from while loop */
     if((fgets(statbuf,BUFLEN,stat_fd[PROC_NET_DEV]) == NULL)) break;
     /* parse the line into fields */
     numfields = parse(statbuf,fields,MAXFIELDNUMBER,BUFLEN);

     /* ETH0 */
     if(strncmp(fields[0],"eth0",4) == 0){
       /* ETH0_RX */
       sprintf(stats[ETH0_RX].name,"eth0_rx");	/* Label it. */
       stats[ETH0_RX].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH0_RX].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH0_RX].current = atof(fields[1]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH0_RX].current = atof(fields[2]);	/* current value (packets) */
       }
       /* ETH0_RX_ERR */
       sprintf(stats[ETH0_RX_ERR].name,"eth0_rx_err");	/* Label it. */
       stats[ETH0_RX_ERR].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH0_RX_ERR].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH0_RX_ERR].current = atof(fields[2]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH0_RX_ERR].current = atof(fields[3]);	/* current value */
       }
       /* ETH0_TX */
       sprintf(stats[ETH0_TX].name,"eth0_tx");	/* Label it. */
       stats[ETH0_TX].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH0_TX].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH0_TX].current = atof(fields[6]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH0_TX].current = atof(fields[10]);	/* current value (packets) */
       }
       /* ETH0_TX_ERR */
       sprintf(stats[ETH0_TX_ERR].name,"eth0_tx_err");	/* Label it. */
       stats[ETH0_TX_ERR].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH0_TX_ERR].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH0_TX_ERR].current = atof(fields[7]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH0_TX_ERR].current = atof(fields[11]);	/* current value (packets) */
       }
       /* ETH0 */
       sprintf(stats[ETH0].name,"eth0");	/* Label it. */
       stats[ETH0].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH0].avail = 1;			/* Yes, we found it */
       stats[ETH0].current = stats[ETH0_RX].current + stats[ETH0_TX].current;	/* current value */
       /* ETH0_ERR */
       sprintf(stats[ETH0_ERR].name,"eth0_err");	/* Label it. */
       stats[ETH0_ERR].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH0_ERR].avail = 1;			/* Yes, we found it */
       stats[ETH0_ERR].current = stats[ETH0_RX_ERR].current + stats[ETH0_TX_ERR].current;	/* current value */
     } /* end eth0 */

     /* ETH1 */
     if(strncmp(fields[0],"eth1",4) == 0){
       /* ETH1_RX */
       sprintf(stats[ETH1_RX].name,"eth1_rx");	/* Label it. */
       stats[ETH1_RX].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH1_RX].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH1_RX].current = atof(fields[1]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH1_RX].current = atof(fields[2]);	/* current value (packets) */
       }
       /* ETH1_RX_ERR */
       sprintf(stats[ETH1_RX_ERR].name,"eth1_rx_err");	/* Label it. */
       stats[ETH1_RX_ERR].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH1_RX_ERR].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH1_RX_ERR].current = atof(fields[2]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH1_RX_ERR].current = atof(fields[3]);	/* current value */
       }
       /* ETH1_TX */
       sprintf(stats[ETH1_TX].name,"eth1_tx");	/* Label it. */
       stats[ETH1_TX].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH1_TX].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH1_TX].current = atof(fields[6]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH1_TX].current = atof(fields[10]);	/* current value (packets) */
       }
       /* ETH1_TX_ERR */
       sprintf(stats[ETH1_TX_ERR].name,"eth1_tx_err");	/* Label it. */
       stats[ETH1_TX_ERR].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH1_TX_ERR].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH1_TX_ERR].current = atof(fields[7]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH1_TX_ERR].current = atof(fields[11]);	/* current value (packets) */
       }
       /* ETH1 */
       sprintf(stats[ETH1].name,"eth1");	/* Label it. */
       stats[ETH1].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH1].avail = 1;			/* Yes, we found it */
       stats[ETH1].current = stats[ETH1_RX].current + stats[ETH1_TX].current;	/* current value */
       /* ETH1_ERR */
       sprintf(stats[ETH1_ERR].name,"eth1_err");	/* Label it. */
       stats[ETH1_ERR].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH1_ERR].avail = 1;			/* Yes, we found it */
       stats[ETH1_ERR].current = stats[ETH1_RX_ERR].current + stats[ETH1_TX_ERR].current;	/* current value */
     } /* end eth1 */

     /* ETH2 */
     if(strncmp(fields[0],"eth2",4) == 0){
       /* ETH2_RX */
       sprintf(stats[ETH2_RX].name,"eth2_rx");	/* Label it. */
       stats[ETH2_RX].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH2_RX].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH2_RX].current = atof(fields[1]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH2_RX].current = atof(fields[2]);	/* current value (packets) */
       }
       /* ETH2_RX_ERR */
       sprintf(stats[ETH2_RX_ERR].name,"eth2_rx_err");	/* Label it. */
       stats[ETH2_RX_ERR].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH2_RX_ERR].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH2_RX_ERR].current = atof(fields[2]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH2_RX_ERR].current = atof(fields[3]);	/* current value */
       }
       /* ETH2_TX */
       sprintf(stats[ETH2_TX].name,"eth2_tx");	/* Label it. */
       stats[ETH2_TX].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH2_TX].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH2_TX].current = atof(fields[6]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH2_TX].current = atof(fields[10]);	/* current value (packets) */
       }
       /* ETH2_TX_ERR */
       sprintf(stats[ETH2_TX_ERR].name,"eth2_tx_err");	/* Label it. */
       stats[ETH2_TX_ERR].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH2_TX_ERR].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH2_TX_ERR].current = atof(fields[7]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH2_TX_ERR].current = atof(fields[11]);	/* current value (packets) */
       }
       /* ETH2 */
       sprintf(stats[ETH2].name,"eth2");	/* Label it. */
       stats[ETH2].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH2].avail = 1;			/* Yes, we found it */
       stats[ETH2].current = stats[ETH2_RX].current + stats[ETH2_TX].current;	/* current value */
       /* ETH2_ERR */
       sprintf(stats[ETH2_ERR].name,"eth2_err");	/* Label it. */
       stats[ETH2_ERR].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH2_ERR].avail = 1;			/* Yes, we found it */
       stats[ETH2_ERR].current = stats[ETH2_RX_ERR].current + stats[ETH2_TX_ERR].current;	/* current value */
     } /* end eth2 */

     /* ETH3 */
     if(strncmp(fields[0],"eth3",4) == 0){
       /* ETH3_RX */
       sprintf(stats[ETH2_RX].name,"eth3_rx");	/* Label it. */
       stats[ETH3_RX].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH3_RX].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH3_RX].current = atof(fields[1]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH3_RX].current = atof(fields[2]);	/* current value (packets) */
       }
       /* ETH3_RX_ERR */
       sprintf(stats[ETH3_RX_ERR].name,"eth3_rx_err");	/* Label it. */
       stats[ETH3_RX_ERR].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH3_RX_ERR].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH3_RX_ERR].current = atof(fields[2]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH3_RX_ERR].current = atof(fields[3]);	/* current value */
       }
       /* ETH3_TX */
       sprintf(stats[ETH3_TX].name,"eth3_tx");	/* Label it. */
       stats[ETH3_TX].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH3_TX].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH3_TX].current = atof(fields[6]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH3_TX].current = atof(fields[10]);	/* current value (packets) */
       }
       /* ETH3_TX_ERR */
       sprintf(stats[ETH3_TX_ERR].name,"eth3_tx_err");	/* Label it. */
       stats[ETH3_TX_ERR].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH3_TX_ERR].avail = 1;			/* Yes, we found it */
       /* 2.0.x or 2.1.x */
       if(kernel.major == 2 && kernel.minor < 2){
         stats[ETH3_TX_ERR].current = atof(fields[7]);	/* current value */
       }
       /* 2.2.x */
       if(kernel.major == 2 && kernel.minor == 2){
         stats[ETH3_TX_ERR].current = atof(fields[11]);	/* current value (packets) */
       }
       /* ETH3 */
       sprintf(stats[ETH3].name,"eth3");	/* Label it. */
       stats[ETH3].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH3].avail = 1;			/* Yes, we found it */
       stats[ETH3].current = stats[ETH3_RX].current + stats[ETH3_TX].current;	/* current value */
       /* ETH3_ERR */
       sprintf(stats[ETH3_ERR].name,"eth3_err");	/* Label it. */
       stats[ETH3_ERR].source = PROC_NET_DEV;		/* Tag its source for xref */
       stats[ETH3_ERR].avail = 1;			/* Yes, we found it */
       stats[ETH3_ERR].current = stats[ETH3_RX_ERR].current + stats[ETH3_TX_ERR].current;	/* current value */
     } /* end eth3 */
   } /* End while(true) */
 }

} /* End init_proc_net_dev */

void get_proc_net_dev()
{
 int i,numfields;

 /* 
  * Now, for a clever trick.  We'll reset the files without actually
  * closing or reopening them.  Perhaps we can save the overhead of
  * an open/close (presumed relatively large, as one has to stat the
  * files in question on EACH open).
  */

 /* PROC_NET_DEV */
 errno = 0;
 if(stat_fd[PROC_NET_DEV]){
   rewind(stat_fd[PROC_NET_DEV]);	/* void, so tough to check errors */
 } else {
   return;
 }
 if(errno == EBADF){
   fprintf(stderr,"Error: The /proc/net/dev file descriptor/stream is not seekable.\n");
   fclose(stat_fd[PROC_NET_DEV]); 
   fprintf(stderr,"Closing and reopening /proc/net/dev.\n");
   stat_fd[PROC_NET_DEV] = fopen("/proc/net/dev","r");
 }

 while(TRUE){
   /* Normal EOF causes break from while loop */
   if((fgets(statbuf,BUFLEN,stat_fd[PROC_NET_DEV]) == NULL)) break;
   /* parse the line into fields */
   numfields = parse(statbuf,fields,MAXFIELDNUMBER,BUFLEN);

   /* ETH0 */
   if(strncmp(fields[0],"eth0",4) == 0){
     /* ETH0_RX */
     stats[ETH0_RX].previous = stats[ETH0_RX].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH0_RX].current = atof(fields[1]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH0_RX].current = atof(fields[2]);	/* current value (packets) */
     }
     /* ETH0_RX_ERR */
     stats[ETH0_RX_ERR].previous = stats[ETH0_RX_ERR].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH0_RX_ERR].current = atof(fields[2]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH0_RX_ERR].current = atof(fields[3]);	/* current value */
     }
     /* ETH0_TX */
     stats[ETH0_TX].previous = stats[ETH0_TX].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH0_TX].current = atof(fields[6]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH0_TX].current = atof(fields[10]);	/* current value (packets) */
     }
     /* ETH0_TX_ERR */
     stats[ETH0_TX_ERR].previous = stats[ETH0_TX_ERR].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH0_TX_ERR].current = atof(fields[7]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH0_TX_ERR].current = atof(fields[11]);	/* current value (packets) */
     }
     /* ETH0 */
     stats[ETH0].previous = stats[ETH0].current;	/* previous value */
     stats[ETH0].current = stats[ETH0_RX].current + stats[ETH0_TX].current;	/* current value */
     /* ETH0_ERR */
     stats[ETH0_ERR].previous = stats[ETH0_ERR].current;	/* previous value */
     stats[ETH0_ERR].current = stats[ETH0_RX_ERR].current + stats[ETH0_TX_ERR].current;	/* current value */
   } /* end eth0 */

   /* ETH1 */
   if(strncmp(fields[0],"eth1",4) == 0){
     /* ETH1_RX */
     stats[ETH1_RX].previous = stats[ETH1_RX].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH1_RX].current = atof(fields[1]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH1_RX].current = atof(fields[2]);	/* current value (packets) */
     }
     /* ETH1_RX_ERR */
     stats[ETH1_RX_ERR].previous = stats[ETH1_RX_ERR].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH1_RX_ERR].current = atof(fields[2]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH1_RX_ERR].current = atof(fields[3]);	/* current value */
     }
     /* ETH1_TX */
     stats[ETH1_TX].previous = stats[ETH1_TX].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH1_TX].current = atof(fields[6]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH1_TX].current = atof(fields[10]);	/* current value (packets) */
     }
     /* ETH1_TX_ERR */
     stats[ETH1_TX_ERR].previous = stats[ETH1_TX_ERR].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH1_TX_ERR].current = atof(fields[7]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH1_TX_ERR].current = atof(fields[11]);	/* current value (packets) */
     }
     /* ETH1 */
     stats[ETH1].previous = stats[ETH1].current;	/* previous value */
     stats[ETH1].current = stats[ETH1_RX].current + stats[ETH1_TX].current;	/* current value */
     /* ETH1_ERR */
     stats[ETH1_ERR].previous = stats[ETH1_ERR].current;	/* previous value */
     stats[ETH1_ERR].current = stats[ETH1_RX_ERR].current + stats[ETH1_TX_ERR].current;	/* current value */
   } /* end eth1 */

   /* ETH2 */
   if(strncmp(fields[0],"eth2",4) == 0){
     /* ETH2_RX */
     stats[ETH2_RX].previous = stats[ETH2_RX].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH2_RX].current = atof(fields[1]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH2_RX].current = atof(fields[2]);	/* current value (packets) */
     }
     /* ETH2_RX_ERR */
     stats[ETH2_RX_ERR].previous = stats[ETH2_RX_ERR].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH2_RX_ERR].current = atof(fields[2]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH2_RX_ERR].current = atof(fields[3]);	/* current value */
     }
     /* ETH2_TX */
     stats[ETH2_TX].previous = stats[ETH2_TX].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH2_TX].current = atof(fields[6]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH2_TX].current = atof(fields[10]);	/* current value (packets) */
     }
     /* ETH2_TX_ERR */
     stats[ETH2_TX_ERR].previous = stats[ETH2_TX_ERR].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH2_TX_ERR].current = atof(fields[7]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH2_TX_ERR].current = atof(fields[11]);	/* current value (packets) */
     }
     /* ETH2 */
     stats[ETH2].previous = stats[ETH2].current;	/* previous value */
     stats[ETH2].current = stats[ETH2_RX].current + stats[ETH2_TX].current;	/* current value */
     /* ETH2_ERR */
     stats[ETH2_ERR].previous = stats[ETH2_ERR].current;	/* previous value */
     stats[ETH2_ERR].current = stats[ETH2_RX_ERR].current + stats[ETH2_TX_ERR].current;	/* current value */
   } /* end eth2 */

   /* ETH3 */
   if(strncmp(fields[0],"eth3",4) == 0){
     /* ETH3_RX */
     stats[ETH3_RX].previous = stats[ETH3_RX].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH3_RX].current = atof(fields[1]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH3_RX].current = atof(fields[2]);	/* current value (packets) */
     }
     /* ETH3_RX_ERR */
     stats[ETH3_RX_ERR].previous = stats[ETH3_RX_ERR].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH3_RX_ERR].current = atof(fields[2]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH3_RX_ERR].current = atof(fields[3]);	/* current value */
     }
     /* ETH3_TX */
     stats[ETH3_TX].previous = stats[ETH3_TX].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH3_TX].current = atof(fields[6]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH3_TX].current = atof(fields[10]);	/* current value (packets) */
     }
     /* ETH3_TX_ERR */
     stats[ETH3_TX_ERR].previous = stats[ETH3_TX_ERR].current;	/* previous value */
     /* 2.0.x or 2.1.x */
     if(kernel.major == 2 && kernel.minor < 2){
       stats[ETH3_TX_ERR].current = atof(fields[7]);	/* current value */
     }
     /* 2.2.x */
     if(kernel.major == 2 && kernel.minor == 2){
       stats[ETH3_TX_ERR].current = atof(fields[11]);	/* current value (packets) */
     }
     /* ETH3 */
     stats[ETH3].previous = stats[ETH3].current;	/* previous value */
     stats[ETH3].current = stats[ETH3_RX].current + stats[ETH3_TX].current;	/* current value */
     /* ETH3_ERR */
     stats[ETH3_ERR].previous = stats[ETH3_ERR].current;	/* previous value */
     stats[ETH3_ERR].current = stats[ETH3_RX_ERR].current + stats[ETH3_TX_ERR].current;	/* current value */
   } /* end eth3 */
 } /* End while(true) */


} /* End get_proc_net_dev() */

void eval_proc_net_dev(){

 int i,numfields;

 for(i=0;i<N_STATS;i++){
   switch(i) {
     /* 
      * ETH[0,1,2,3]_X are all rates.
      */
     /* ETH0 */
     case ETH0:
     case ETH0_ERR:
     case ETH0_RX:
     case ETH0_RX_ERR:
     case ETH0_TX:
     case ETH0_TX_ERR:
     /* ETH1 */
     case ETH1:
     case ETH1_ERR:
     case ETH1_RX:
     case ETH1_RX_ERR:
     case ETH1_TX:
     case ETH1_TX_ERR:
     /* ETH2 */
     case ETH2:
     case ETH2_ERR:
     case ETH2_RX:
     case ETH2_RX_ERR:
     case ETH2_TX:
     case ETH2_TX_ERR:
     /* ETH3 */
     case ETH3:
     case ETH3_ERR:
     case ETH3_RX:
     case ETH3_RX_ERR:
     case ETH3_TX:
     case ETH3_TX_ERR:
       stats[i].rate = (stats[i].current - stats[i].previous)/interval;
       if(stats[i].rate < 0.0) stats[i].rate = 0.0;
       break;
     default:
       break;
   } /* End case switch */
 } /* End loop through enumerated types */

} /* End eval_proc_net_dev */
