Logo Search packages:      
Sourcecode: netdiag version File versions  Download package

statnetd.c

/*  statnetd.c is part of Statnet */
/* Statnet is protected under the GNU Public License (GPL2). */
/* Author: Jeroen Baekelandt (jeroenb@igwe.vub.ac.be)       */
/* 13DEC98: Scot E. Wilcoxon (sewilco@fieldday.mn.org)     */

/* This is the main program for the monitoring daemon */
#define MAIN_LINE 1

#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <stdio.h>
#include <sys/utsname.h>

#include <sys/ipc.h>
#ifdef IPC_DIPC
#include <linux/dipc.h>
#else
/* Always define so all compilations can run distributed. */
#define IPC_DIPC 00010000     /* make it distributed */
#ifndef DIPC_SIG_READER
#define DIPC_SIG_READER SIGURG      /* for compilation on non-DIPC systems */
#endif
#ifndef DIPC_SIG_WRITER
#define DIPC_SIG_WRITER SIGPWR      /* for compilation on non-DIPC systems */
#endif
#endif

#include <sys/shm.h>

#define Stringify(X)    #X
#define Quoteify(X)     Stringify(X)

#if !(defined(__GLIBC__) && __GLIBC__ >= 2)
#include <linux/if_ether.h>
#include <linux/if.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#else
#include <netinet/if_ether.h>
#include <net/if.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#endif
#include <errno.h>
#include <values.h>
#include "stat.h"

#ifdef _LINUX_IF_ETHER_H
#undef NET_3                  /* not using Net/3 definitions */
#endif

#ifndef ETH_HLEN
#define ETH_HLEN 14           /* Ethernet header length */
#endif

#ifndef ETH_P_ATALK
#define ETH_P_ATALK 0x809B    /* Appletalk */
#endif

#ifndef SOCK_PACKET
#define SOCK_PACKET SOCK_RAW  /* If SOCK_PACKET is wrong, try SOCK_RAW */
#endif

#ifndef NET_3
#define ether_head      ethhdr      /* ether_head structure */
#define ether_type      h_proto     /* Ethernet Packet Type ID field */
#define ip        iphdr /* IP header structure */
#define ip_off          frag_off    /* IP protocol field */
#define ip_p            protocol    /* IP protocol field */
#define ip_hl           ihl   /* IP header length field */
#define th_sport  source      /* TCP source port field */
#define th_dport  dest  /* TCP destination port field */
#define ui_sport  source      /* UDP source port field */
#define ui_dport  dest  /* UDP destination port field */
#endif

#if 1
#define SN_RCV_BUF_SIZE 1600
#else
#define SN_RCV_BUF_SIZE (sizeof(struct ether_head)+ \
                         sizeof(struct ip)+ \
                         sizeof(struct options)+ \
                         sizeof(struct tcphdr))
                              /* above was 1600, but kernel discards */
                              /* excess and tells us full length,   */
                              /* so we only need enough to analyze. */
/* Removed the above precision because Linux 1.1.* delivered only the size */
/* requested, but by Linux 2.0.* this optimization no longer worked. */
#endif

struct at_frame_type
  {
    unsigned char filler[20];
#if !(defined(__GLIBC__) && __GLIBC__ >= 2)
    __u16 appletalk_type1;    /* what is formal name? */
    unsigned char filler2[12];
    __u8 appletalk_type2;     /* what is formal name? */
#else
    u_int16_t appletalk_type1;      /* what is formal name? */
    unsigned char filler2[12];
    u_int8_t appletalk_type2; /* what is formal name? */
#endif
  };                    /* Ethernet Appletalk */

void handle_frame (unsigned char *buf, int length, struct sockaddr *saddr);
void handle_ip (struct ip *buf, int length);
void signal_handler (int signal_number);

int shutdown_flag = 0;
struct StatMemStruct *StatMem;      /* pointer to shared memory segment */

main (int argc, char *argv[])
{
  int daemon_option = 0;
  int length;
  int sd;
  int shmid;                  /* shared memory ID */
  int sizeaddr;
  char interface_name[STATNETD_IFACE_LEN+1];    /* name of interface */
  char server_label[STATNETD_NAME_LEN+1]; /* name of this server */
  struct ifreq ifr, oldifr;
  struct sockaddr saddr;
  struct utsname utsbuf;
  unsigned char buf[SN_RCV_BUF_SIZE];
  key_t mem_key;
  extern char *optarg;              /* set by getopt(3) */
  extern int optind, opterr, optopt;      /* set by getopt(3) */

  mem_key = (key_t)STAT_IPC_KEY;
  memset( interface_name, 0, STATNETD_IFACE_LEN+1 );
  strcpy( interface_name, ETH);
  timer_flag = 0;

  memset( server_label, 0, STATNETD_NAME_LEN+1 );
  if( uname(&utsbuf) != 0 )
  {  /* if error getting system name */
      strcpy( server_label, "unknown server" );
  }  /* if error getting system name */
  else
  {  /* else copy node name */
        strncpy( server_label, utsbuf.nodename, STATNETD_NAME_LEN );
  }  /* else copy node name */

  if ( 
          ( signal( SIGINT,   signal_handler ) == SIG_ERR ) ||
          ( signal( SIGQUIT,  signal_handler ) == SIG_ERR ) ||
          ( signal( SIGCHLD,  SIG_IGN ) == SIG_ERR ) ||
          /* Ignore DIPC signals which this app does not care about */
/* sparc doesn't have SIGPWR.  --rcw 19991024 */
#ifndef __sparc__
          ( signal( DIPC_SIG_READER, SIG_IGN ) == SIG_ERR ) ||
          ( signal( DIPC_SIG_WRITER, SIG_IGN ) == SIG_ERR ) ||
#endif
          ( signal( SIGUSR1,  signal_handler ) == SIG_ERR ) ||
          ( signal( SIGUSR2,  signal_handler ) == SIG_ERR ) 
      )
    {
      perror ("Can't register signal handler");
      exit (5);
    }

    /* Default settings */
    options.g = 1;            /* General */
    options.ip_option = 1;    /* IP protocols */
    options.at_option = 1;    /* Appletalk activity */
    options.prot_option = 1;  /* Protocol activity */
    options.tcp_option = 1;   /* TCP/IP activity */
    options.udp_option = 1;   /* UDP/IP activity */
    options.sap_option = 1;   /* SAP activity */

    if( argc != 1 )
    {  /* if there are command-line arguments */
      int op;

      while ((op = getopt (argc, argv, "acdghik:n:pstuw:")) != EOF)
      {
        switch (op)
          {
          case 'a':
            options.at_option = 1;
            break;
          case 'c':
            /* clear options */
            options.g = 0;          /* General */
            options.ip_option = 0;  /* IP protocols */
            options.at_option = 0;  /* Appletalk activity */
            options.prot_option = 0;      /* Protocol activity */
            options.tcp_option = 0; /* TCP/IP activity */
            options.udp_option = 0; /* UDP/IP activity */
            options.sap_option = 0; /* SAP activity */
            mem_key = (key_t)STAT_IPC_KEY;
            memset( interface_name, 0, STATNETD_IFACE_LEN+1 );
            strcpy( interface_name, ETH);

            memset( server_label, 0, STATNETD_NAME_LEN+1 );
            if( uname(&utsbuf) != 0 )
            {  /* if error getting system name */
            strcpy( server_label, "unknown server" );
            }  /* if error getting system name */
            else
            {  /* else copy node name */
              strncpy( server_label, utsbuf.nodename, STATNETD_NAME_LEN );
                  }  /* else copy node name */
              break;
          case 'd':
            daemon_option = 1;
            break;
          case 'g':
            options.g = 1;
            break;
          case 'i':
            options.ip_option = 1;
            break;
          case 'k':
            if( optarg == (char *)NULL) usage(argv[0]);
            mem_key = (key_t)strtol(optarg, (char **)NULL, 0);
            break;
          case 'n':
            if( optarg == (char *)NULL) usage(argv[0]);
            memset( server_label, 0, STATNETD_NAME_LEN+1 );
            strncpy( server_label, optarg, STATNETD_NAME_LEN );
            break;
          case 'p':
            options.prot_option = 1;
            break;
          case 's':
            options.sap_option = 1;
            break;
          case 't':
            options.tcp_option = 1;
            break;
          case 'u':
            options.udp_option = 1;
            break;
          case 'w':
            if( optarg == (char *)NULL) usage(argv[0]);
            memset( interface_name, 0, STATNETD_IFACE_LEN+1 );
            strncpy( interface_name, optarg, STATNETD_IFACE_LEN );
            break;
          case 'h':
          default:
            usage (argv[0]);
            exit(0);
            break;
          }
      }
    }  /* if there are command-line arguments */

  /* Initialize shared memory */
  if ((shmid = shmget(mem_key, sizeof(struct StatMemStruct), 
        IPC_DIPC|IPC_CREAT|IPC_EXCL|0644)) == -1 )
  {  /* if it might already exist, use it */
        if ((shmid = shmget(mem_key, sizeof(struct StatMemStruct), 
              IPC_DIPC)) == -1 )
        {  /* error, could not find shared memory segment */
            perror ("Can't get shared memory");
            exit (6);
        }  /* error, could not find shared memory segment */

  }  /* if it might already exist, use it */
  if(( StatMem = (struct StatMemStruct *)shmat(shmid, 0, 0) ) == (char *)-1)
  { /* if error in attaching with write permission */
      perror ("Can't attach shared memory");
      exit (7);
  } /* if error in attaching with write permission */

  {   /* Compound statement to make initializers vanish after init. */

    memset (&SM_regis, 0, sizeof (struct registers));
    memset (StatMem, 0, sizeof (struct StatMemStruct));
    strncpy( StatMem->servername, server_label, STATNETD_NAME_LEN );

    tally_init ( &StatMem->prot, disabled,
      (unsigned int     *)0,
      -1, (int    *)0,
      -1, (char         *)0,
      StatMem->prot_types, StatMem->protocol_count, protocol_num,
      SN_NUM_PROTOCOLS-1, SN_MAX_PROTO_DESC, (char *)0);
    tally_init ( &StatMem->ip_types, disabled,
      StatMem->ip_protocol_count, 
      -1, (int    *)0,
      SN_MAX_IP_PORT, (char *)0,
      (unsigned int *)0, (unsigned int *)0, 0,
      0, 0, (char *)0);
    tally_init ( &StatMem->tcp_port, disabled,
      StatMem->tcp_port_ctr, 
      -1, (int    *)0,
      SN_MAX_TCP_PORTS, (char *)0,
      (unsigned int *)0, (unsigned int *)0, 0,
      0, 0, (char *)0);
    tally_init ( &StatMem->udp_port, disabled,
      StatMem->udp_port_ctr,
      -1, (int    *)0,
      SN_MAX_UDP_PORTS, (char *)0,
      (unsigned int *)0, (unsigned int *)0, 0,
      0, 0, (char *)0);
    tally_init ( &StatMem->sap_types, disabled,
      StatMem->sap_count, 
      -1, (int    *)0,
      SN_MAX_SAP, (char *)0,
      (unsigned int *)0, (unsigned int *)0, 0,
      0, 0, (char *)0);

      if( daemon_option )
      {  /* if should run in the background */
            int pid;
            int fileDesc = -1;

            close(0);   /* close stdin */
            close(1);   /* close stdout */
            close(2);   /* close stderr */
            if( (pid = fork()) < 0 )
            {  /* error, could not become a background task */
                  exit(10);
            }  /* error, could not become a background task */
            if( pid != 0 ) exit(0);       /* end the original program */

            (void) setsid();  /* process group leader */

            if( (pid = fork()) < 0 )
            {  /* error, could not become a background task */
                  exit(10);
            }  /* error, could not become a background task */
            if( pid != 0 ) exit(0);       /* end the original program */

            fileDesc = open( "/dev/null", O_RDWR);    /* stdin */
            (void) dup(fileDesc);   /* stdout */
            (void) dup(fileDesc);   /* stderr */
      }  /* if should run in the background */


    /* OPEN SOCKET */

    if ((sd = socket (AF_INET, SOCK_PACKET, htons (ETH_P_ALL))) < 0)
      {
      perror ("Can't get socket");
      exit (1);
      }

    /* SET PROMISC */

    strcpy (oldifr.ifr_name, interface_name);
    if (ioctl (sd, SIOCGIFFLAGS, &oldifr) < 0)
      {
      close (sd);
      perror ("Can't get flags");
      exit (2);
      }

    /* Should this be rewritten to cooperate with other net tools? */
    memcpy( &ifr, &oldifr, sizeof( struct ifreq ) );
    ifr.ifr_flags |= IFF_PROMISC;

    if (ioctl (sd, SIOCSIFFLAGS, &ifr) < 0)
      {
      close (sd);
      perror ("Can't set flags");
      exit (3);
      }

    StatMem->prot.type_code = options.prot_option ? protocol : disabled;
    StatMem->ip_types.type_code = options.ip_option ? ip_prot : disabled;
    StatMem->tcp_port.type_code = options.tcp_option ? tcp : disabled;
    StatMem->udp_port.type_code = options.udp_option ? udp : disabled;
    StatMem->sap_types.type_code = options.sap_option ? sap : disabled;

    SM_regis.errcode = 0;
    SM_regis.errcount = 0;

    SM_regis.rx_errors_d = 0;
    SM_regis.rx_dropped_d = 0;
    SM_regis.rx_packets_d = 0;
    SM_regis.rx_interval = 1;

#if 0
/* removed for statnet 3.* due to awkwardness in reading data. */
#if !( defined(__GLIBC__) && __GLIBC__ >= 2 )
    memset( &stat_buf1, 0, sizeof(struct enet_statistics) );
    memset( &stat_buf2, 0, sizeof(struct enet_statistics) );
#else
    memset( &stat_buf1, 0, sizeof(struct net_device_stats) );
    memset( &stat_buf2, 0, sizeof(struct net_device_stats) );
#endif
    last_stats = &stat_buf1;
    now_stats = &stat_buf2;
    if_getstats (interface_name, last_stats);        /* get starting interface statistics */
#endif

  }                     /* Compound statement to make initializer variables vanish after init. */
  /* END OF INITIALISATION */

  set_null ( StatMem );             /* clear all variables */
  services();                 /* default values for services */

  while (!shutdown_flag)
    {                   /* while no shutdown requested */
      /* This is the main data-gathering loop; keep it small and fast */
      sizeaddr = sizeof(struct sockaddr); /* size of saddr */
      length = recvfrom (sd, buf, SN_RCV_BUF_SIZE, 0, &saddr, &sizeaddr);

      if (length < 0)
      {  /* if length < 0 */
      if (errno != EINTR)
        {               /* if error detected and error is not expected type */
          SM_regis.errcode = errno;
          SM_regis.errcount++;
          continue;
        }
      else
        continue;
      }  /* if length < 0 */
      else
      handle_frame (buf, length, &saddr);

      if( !timer_flag )
      {  /* if timer not running */
        if (signal (SIGALRM, itstime) == SIG_ERR)
      {
        SM_regis.errcode = errno;
        SM_regis.errcount++;
        timer_flag = 0;
      }
      else
      {  /* else signal registered */
        alarm (SN_STATS_SECS);
        timer_flag = 1;
      }  /* else signal registered */
      }  /* if timer not running */
                                      
    }                   /* while no shutdown requested */


  /* TERMINATE */

  /* Should this be rewritten to cooperate with other net tools? */
  if (ioctl (sd, SIOCSIFFLAGS, &oldifr) < 0)
    {
      close (sd);
      perror ("Can't unset flags");
      exit (4);
    }

  close (sd);
  shmdt( (char *)StatMem );   /* detach shared memory */
  exit (0);
}


void
exatalk (struct at_frame_type *buf, int length)
{
  /* Need some documentation of these definitions and the AT packet types */
  switch (buf->appletalk_type2)     /* Appletalk */
    {
    case 0x01:
      SM_regis.rtmprd++;
      break;
    case 0x02:
      SM_regis.nbp++;
      break;
    case 0x03:
      SM_regis.atp++;
      break;
    case 0x04:
      SM_regis.aep++;
      break;
    case 0x05:
      SM_regis.rtmpreq++;
      break;
    case 0x06:
      SM_regis.zip++;
      break;
    case 0x07:
      SM_regis.adsp++;
      break;
    default:
      break;
    }
}

void
handle_other (unsigned char *buf, int length)
{

  /* frame_protocol is global */
  if (frame_protocol < 1501)
    {                   /* if IEEE 802.3 packet instead of Ethernet packet (per RFC 1700) */
      if ((short int) buf[14] <= StatMem->sap_types.c_max)
      {
        tally( (short int)buf[14], &StatMem->sap_types );   /* count 802.2 SAP number */
      }
      SM_regis.new_ethernet_count++;
    }                   /* if IEEE 802.3 packet instead of Ethernet packet */
  else
    {                   /* else is an Ethernet packet */
      switch (htons (((struct at_frame_type *) buf)->appletalk_type1))  /* Appletalk */
      {
      case ETH_P_ATALK:
        if (options.at_option)
          exatalk ((struct at_frame_type *) buf, length);
        break;
      case ETH_P_AARP:
        SM_regis.aarp++;
        break;
      default:
        break;
      }
    }                   /* else is an Ethernet packet */
}

void
handle_ip (struct ip *buf, int length)
{
  static int src_port, dest_port;

  if (buf->ip_p < StatMem->ip_types.c_max)
    {                   /* if IP protocol type is to be tallied */
      tally( buf->ip_p, &StatMem->ip_types );   /* count IP protocol */
    }                   /* if IP protocol type is to be tallied */

  switch (buf->ip_p)          /* IP Protocol */
    {

    case IPPROTO_TCP:         /* TCP */
      {

      /* Fix to ignore "Don't Fragment" packets pointed out by spock@phoenix.earthlight.co.nz */
      if (
#if (__BYTE_ORDER == __BIG_ENDIAN)
           (buf->ip_off != 0) && ((buf->ip_off & 0x4000) == 0)
#elif (__BYTE_ORDER == __LITTLE_ENDIAN)
           (buf->ip_off != 0) && ((buf->ip_off & 0x0040) == 0)
#else
#error      "Please fix <endian.h>"
#endif
        )
        {               /* if this is not the first frame of a fragmented packet */
          tally( 0, &StatMem->tcp_port ); /* count fragment */
        }               /* if this is not the first frame of a fragmented packet */
      else
        {               /* else this is the first frame of a packet */
          /* The below may count packets twice, but probably both are not displayed */
          if (buf->ip_hl == 5)
            {                 /* if IP header is normal length we can assume 20 octects length */
            if ((src_port = ntohs (((struct tcphdr *) ((void *) buf + 20))->th_sport)) <= SN_MAX_TCP_PORTS)
                tally( src_port, &StatMem->tcp_port );      /* count source port */
            if ((dest_port = ntohs (((struct tcphdr *) ((void *) buf + 20))->th_dport)) <= SN_MAX_TCP_PORTS)
              if (dest_port != src_port)
                {       /* ignore when dest same as src to avoid apparent over-tallying */
                  tally( dest_port, &StatMem->tcp_port );
                }       /* ignore when dest same as src to avoid apparent over-tallying */
            }                 /* IP header normal length */
          else
            {                 /* IP header with options */
            /* Incidentally, the (void *) is to cause byte-level math not sizeof(struct ip) */
            if ((src_port = ntohs (((struct tcphdr *) ((void *) buf + ((buf->ip_hl) * 4)))->th_sport)) <= SN_MAX_TCP_PORTS)
                tally( src_port, &StatMem->tcp_port );      /* count source port */
            if ((dest_port = ntohs (((struct tcphdr *) ((void *) buf + ((buf->ip_hl) * 4)))->th_dport)) <= SN_MAX_TCP_PORTS)
              if (dest_port != src_port)
                {       /* ignore when dest same as src to avoid apparent over-tallying */
                  tally( dest_port, &StatMem->tcp_port );
                }       /* ignore when dest same as src to avoid apparent over-tallying */
            }                 /* IP header with options */
        }               /* else this is the first frame of a packet */
      }
      break;

    case IPPROTO_UDP:         /* UDP */
      {
      /* Fix to ignore "Don't Fragment" packets pointed out by spock@phoenix.earthlight.co.nz */
      if (
#if (__BYTE_ORDER == __BIG_ENDIAN)
           (buf->ip_off != 0) && ((buf->ip_off & 0x4000) == 0)
#elif (__BYTE_ORDER == __LITTLE_ENDIAN)
           (buf->ip_off != 0) && ((buf->ip_off & 0x0040) == 0)
#else
#error      "Please fix <endian.h>"
#endif
        )
        {               /* if this is not the first frame of a fragmented packet */
          tally( 0, &StatMem->udp_port ); /* count fragment */
        }               /* if this is not the first frame of a fragmented packet */
      else
        {               /* else this is the first frame of a packet */
          /* The below may count packets twice, but probably both are not displayed */
          if (buf->ip_hl == 5)
            {                 /* if IP header is normal length we can assume 20 octects length */
            if ((src_port = ntohs (((struct udphdr *) ((void *) buf + 20))->ui_sport)) <= SN_MAX_UDP_PORTS)
              tally( src_port, &StatMem->udp_port ); /* count source port */
            if ((dest_port = ntohs (((struct udphdr *) ((void *) buf + 20))->ui_dport)) <= SN_MAX_UDP_PORTS)
              if (dest_port != src_port)
                {       /* ignore when dest same as src to avoid apparent over-tallying */
                  tally( dest_port, &StatMem->udp_port );
                }       /* ignore when dest same as src to avoid apparent over-tallying */
            }                 /* IP header normal length */
          else
            {                 /* IP header with options */
            /* Incidentally, the (void *) is to cause byte-level math not sizeof(struct ip) */
            if ((src_port = ntohs (((struct tcphdr *) ((void *) buf + ((buf->ip_hl) * 4)))->ui_sport)) <= SN_MAX_UDP_PORTS)
              tally( src_port, &StatMem->udp_port ); /* count source port */
            if ((dest_port = ntohs (((struct tcphdr *) ((void *) buf + ((buf->ip_hl) * 4)))->ui_dport)) <= SN_MAX_UDP_PORTS)
              if (dest_port != src_port)
                {       /* ignore when dest same as src to avoid apparent over-tallying */
                  tally( dest_port, &StatMem->udp_port );
                }       /* ignore when dest same as src to avoid apparent over-tallying */
            }                 /* IP header with options */
        }               /* else this is the first frame of a packet */
      }

      break;

    default:
      /* Don't increment "Other" because are not displaying "Other IP" counts */
      /* This packet does show in the "IP" total, but not elsewhere. */
      break;
    }
}

void
handle_frame (unsigned char *buf, int length, struct sockaddr *saddr)
{
  int prot_int;
  int search_int;
  int prot_now;
  struct ip *ip_ptr;

  ip_ptr = (struct ip *) ((void *) buf + ETH_HLEN);

  if (length > 0)
    {

      packet_type = ((struct ether_head *) buf)->ether_type;      /* Ethernet packet type ID field */
      frame_protocol = ntohs (packet_type);     /* Convert from network to host seq */
      if (frame_protocol < 1501)
      {                 /* if an IEEE 802.3 packet */
        frame_protocol = SN_PROT_IEEE802_3;
      }                 /* if an IEEE 802.3 packet */

      /* The grand totals by interface type */
      if (strncmp (saddr->sa_data, "eth", 3) == 0)
      {
        SM_regis.etherbytes += length;
        SM_regis.ethercount++;
      }
      else if (strncmp (saddr->sa_data, "plip", 4) == 0)
      {
        SM_regis.plipbytes += length;
        SM_regis.plipcount++;
      }
      else if (strncmp (saddr->sa_data, "lo", 2) == 0)
      {
        SM_regis.loopbytes += length;
        SM_regis.loopcount++;
        frame_protocol = SN_PROT_LOOP;
      }
      else if (strncmp (saddr->sa_data, "ppp", 3) == 0)
      {
        SM_regis.pppbytes += length;
        SM_regis.pppcount++;
        frame_protocol = SN_PROT_PPP;
        ip_ptr = (struct ip *) ((void *) buf);  /* No Ethernet Header */
      }
      else if (strncmp (saddr->sa_data, "sl", 2) == 0)
      {
        SM_regis.slipbytes += length;
        SM_regis.slipcount++;
        frame_protocol = SN_PROT_SLIP;
        ip_ptr = (struct ip *) ((void *) buf);  /* No Ethernet Header */
      }
      else
      {
        SM_regis.otherbytes += length;
        SM_regis.othercount++;
      }

            if( tally( frame_protocol, &StatMem->prot ) > 0 )
            {           /* if protocol was not found */
              SM_regis.unknown_type++;
              SM_regis.unknown_frame_type = frame_protocol;
            }           /* if protocol was not found */

      switch (frame_protocol)
      {
      case ETH_P_IP:
      case SN_PROT_PPP:
      case SN_PROT_SLIP:
      case SN_PROT_LOOP:
        if (options.tcp_option || options.udp_option || options.ip_option)
          handle_ip (ip_ptr, length);
        break;
      case ETH_P_ATALK:
        if (options.at_option)
          exatalk ((struct at_frame_type *) ((void *) buf + ETH_HLEN), length);
        break;
      default:
        if (options.ip_option || options.at_option)
          handle_other (buf, length);
        break;
      }

    }                   /* if length > 0 */
}

void signal_handler (int signal_number)
{
      shutdown_flag = 1;      /* shut down upon any signal */
}

void
usage (char *arg)
{
  fprintf (stderr, "\n%s [-adgipstuh] [-k key] [-n name] [-w interface]\n\n", arg);
  fprintf (stderr, "   Gather network statistics\n");
  fprintf (stderr, "   version " Quoteify(SNVERSION) "\n\n");
  fprintf (stderr, "    -a       gather Appletalk statistics\n");
  fprintf (stderr, "    -c       clear the other option settings\n");
  fprintf (stderr, "    -d       daemonize (run in background)\n");
  fprintf (stderr, "    -g       gather General statistics\n");
  fprintf (stderr, "    -i       gather IP Protocols statistics\n");
  fprintf (stderr, "    -k key   define shared memory key (base 8, 10, 16)\n");
  fprintf (stderr, "    -n name  label this server with this name\n");
  fprintf (stderr, "    -p       gather Protocols statistics\n");
  fprintf (stderr, "    -s       gather IEEE 802.2 SAP statistics\n");
  fprintf (stderr, "    -t       gather TCP/IP statistics\n");
  fprintf (stderr, "    -u       gather UDP/IP statistics\n");
  fprintf (stderr, "    -w eth0  interface to watch\n");
  fprintf (stderr, "    -h       show this message\n");
  fprintf (stderr, "    no options: gather most statisticss\n");
  exit (0);
}

Generated by  Doxygen 1.6.0   Back to index