home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-09-11 | 40.7 KB | 1,823 lines |
- Subject: v13i031: Remote statistics server
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Dave Curry <davy@intrepid.ecn.purdue.edu>
- Posting-number: Volume 13, Issue 31
- Archive-name: rstat
-
- This is a remote statistics server for BSD. With it you can write
- survey programs to collect statistics on things like load averages,
- number of users, uptime, and general network statistics from remote
- machines. It implements the server described by Dave Mills in RFC996,
- "Statistics Server", February 1987.
-
- It has been tested on a Vax-11/780 running 4.3BSD, a Gould PN9080
- running UTX/32 2.0 (4.3BSD), a Sun 3/180 and a Sun 3/50 running Sun
- 3.3 (4.2BSD), and a CCI 6/32 running 4.3BSD. It should work equally
- well under 4.2BSD. (Note: on real new 4.3BSD, like on the CCI 6/32,
- change "sys/dk.h" to "sys/dkstat.h" in getcpustats.c - I wish Berkeley
- would make up their minds!)
-
- # This is a shell archive. Save this into a file, edit it
- # and delete all lines above this comment. Then give this
- # file to sh by executing the command "sh file". The files
- # will be extracted into the current directory owned by
- # you with default permissions.
- #
- # The files contained herein are:
- # README Makefile stats.1 statsrv.8
- # stats.h dg_sendrecv.c getcpustats.c getloadstats.c
- # getnetstats.cgettablestats.c gettimestats.c getuserstats.c
- # st_sendrecv.c stats.c statsrv.c tester
- # rfc
- #
- echo 'x - README'
- sed 's/^X//' <<'________This_Is_The_END________' >>README
- XThis is a remote statistics server as described in RFC996, "Statistics
- XServer", D. L. Mills, February 1987. With it, you can collect things
- Xlike load averages, number of users, uptime, and network statistics
- Xfrom remote machines easily.
- X
- XIt has been tested on a Vax-11/780 running 4.3BSD, a Gould PN9080
- Xrunning UTX/32 2.0 (4.3BSD), a Sun 3/180 and a Sun 3/50 running Sun
- X3.3 (4.2BSD), a CCI 6/32 running 4.3BSD, and a Sequent running Dynix.
- XIt should work equally well under 4.2BSD. (Note: on real new 4.3BSD,
- Xlike on the CCI 6/32, change "sys/dk.h" to "sys/dkstat.h" in
- Xgetcpustats.c - I wish Berkeley would make up their minds!)
- X
- XOn Suns, you will want to edit "Makefile" and add "-fswitch" to CFLAGS,
- Xand change the install for "statsrv" to put it in "/usr/etc/in.statsrv".
- XAfter you have made and installed the programs, edit "/etc/inetd.conf"
- Xand add the lines:
- X
- Xstatsrv stream tcp nowait root /etc/statsrv statsrv
- Xstatsrv dgram udp wait root /etc/statsrv statsrv
- X
- XThen kill -1 inetd. On Suns, instead of "/etc/inetd.conf", edit
- X"/etc/servers" and add the lines:
- X
- Xstatsrv tcp /usr/etc/in.statsrv
- Xstatsrv udp /usr/etc/in.statsrv
- X
- XThen kill inetd and restart it.
- X
- XIf you don't keep up with the NIC, you may need to add the following
- Xlines to "/etc/services":
- X
- Xstatsrv 133/tcp # statistics server
- Xstatsrv 133/udp
- X
- XGood luck.
- X
- XDave Curry
- XPurdue University
- XEngineering Computer Network
- Xdavy@intrepid.ecn.purdue.edu
- X{ihnp4, rutgers, iuvax}!pur-ee!davy
- ________This_Is_The_END________
- echo 'x - Makefile'
- sed 's/^X//' <<'________This_Is_The_END________' >>Makefile
- X#
- X# $Header: /ecn1/src/ecn/statsrv/RCS/Makefile,v 1.3 87/12/08 14:39:43 davy Exp $
- X#
- X# Makefile for stats and statsrv.
- X#
- X# David A. Curry
- X# Purdue University
- X# Engineering Computer Network
- X# davy@intrepid.ecn.purdue.edu
- X# October, 1987
- X#
- X# $Log: Makefile,v $
- X# Revision 1.3 87/12/08 14:39:43 davy
- X# Added lines for gettablestats.c.
- X#
- X# Revision 1.2 87/10/29 14:23:50 davy
- X# Updated dependencies.
- X#
- X# Revision 1.1 87/10/17 21:00:57 davy
- X# Initial revision
- X#
- X#
- XCFLAGS= -O
- XDESTDIR=
- X
- XSTATS= stats.o dg_sendrecv.o st_sendrecv.o
- XSTATSRV=statsrv.o dg_sendrecv.o st_sendrecv.o getcpustats.o getloadstats.o \
- X getnetstats.o gettablestats.o gettimestats.o getuserstats.o
- X
- Xall: stats statsrv
- X
- Xstats: $(STATS)
- X $(CC) $(CFLAGS) -o stats $(STATS)
- X
- Xstatsrv: $(STATSRV)
- X $(CC) $(CFLAGS) -o statsrv $(STATSRV)
- X
- Xinstall: all
- X install -c -s stats $(DESTDIR)/usr/ecn/stats
- X install -c -s statsrv $(DESTDIR)/etc/statsrv
- X
- Xtags:
- X @ctags *.c > tags
- X
- Xclean:
- X rm -f a.out core *.o
- X
- Xzap: clean
- X rm -f stats statsrv
- X
- Xstats.o: stats.c stats.h
- Xdg_sendrecv.o: dg_sendrecv.c stats.h
- Xst_sendrecv.o: st_sendrecv.c stats.h
- Xgetcpustats.o: getcpustats.c stats.h
- Xgetnetstats.o: getnetstats.c
- Xgetloadstats.o: getloadstats.c stats.h
- Xgettimestats.o: gettimestats.c stats.h
- Xgetuserstats.o: getuserstats.c stats.h
- Xgettablestats.o: gettablestats.c
- ________This_Is_The_END________
- echo 'x - stats.1'
- sed 's/^X//' <<'________This_Is_The_END________' >>stats.1
- X.TH STATS 1 "17 October 1987" ECN
- X.SH NAME
- Xstats \- gather remote statistics
- X.SH SYNOPSIS
- X.B stats
- X[
- X.B \-d
- X]
- X.I hostname
- X.I statname
- X[
- X.IR statname ...
- X]
- X.SH DESCRIPTION
- X.PP
- X.B Stats
- Xis used to gather statistics from remote hosts by connecting to a
- Xstatistics server on internet port 133 (see
- X.BR statsrv (8)).
- XStatistics names are based on the remote host's command language,
- Xtry using the ``help'' statistic to get a list.
- X.PP
- XBy default,
- X.B stats
- Xuses a stream (\s-1TCP\s0) connection;
- Xif the
- X.B \-d
- Xflag is given as the first argument,
- Xdatagrams (\s-1UDP\s0) will be used instead.
- XNot all statistics servers support stream connections.
- X.SH SEE ALSO
- X.BR statsrv (8)
- X.br
- X\s-1RFC996\s0,
- X.IR "Statistics Server" ,
- XD. L. Mills,
- XFebruary 1987.
- X.SH AUTHOR
- XDavid A. Curry,
- XPurdue University Engineering Computer Network
- ________This_Is_The_END________
- echo 'x - statsrv.8'
- sed 's/^X//' <<'________This_Is_The_END________' >>statsrv.8
- X.TH STATSRV 8 "8 December 1987" ECN
- X.SH NAME
- Xstatsrv \- statistics server
- X.SH SYNOPSIS
- X.B statsrv
- X.SH DESCRIPTION
- X.PP
- X.B Statsrv
- Xis invoked by
- X.BR inetd (8)
- Xwhen connections or datagrams arrive on internet port 133.
- XIt understands both stream (\s-1TCP\s0) and datagram (\s-1UDP\s0)
- Xconnections.
- X.PP
- X.B Statsrv
- Xreads null-terminated strings requesting statistics,
- Xand returns null-terminated strings suitable for printing on a terminal
- Xor line printer.
- XThe special statistic name ``help'' may be sent to request a list of
- Xknown commands.
- XAs of this writing,
- Xthe known commands are:
- X.IP \fBactusers\fP \w'boottimeXX'u
- XThe number of active users (those users idle less than one hour)
- Xis returned.
- X.IP \fBboottime\fP \w'boottimeXX'u
- XThe time the system was last booted is returned.
- X.IP \fBcpu\fP \w'boottimeXX'u
- XThe cpu utilization,
- Xbroken down into percentages of user,
- Xnice,
- Xsystem,
- Xand idle time,
- Xis returned.
- X.IP \fBdate\fP \w'boottimeXX'u
- XThe current date is returned.
- X.IP \fBhelp\fP \w'boottimeXX'u
- XA list of known commands,
- Xseparated by newlines,
- Xis returned.
- X.IP \fBloadav\fP \w'boottimeXX'u
- XThe one-minute load average,
- Xan average of the number of runnable jobs,
- Xis returned.
- X.IP \fBmbufs\fP \w'boottimeXX'u
- XA summary of network buffer (mbufs) utilization is returned.
- XThis is the output from
- X.BR "netstat \-m" .
- X.IP \fBpackets\fP \w'boottimeXX'u
- XA summary of input and output packets on the network interfaces is
- Xreturned.
- XThis is the output from
- X.BR "netstat \-i" .
- X.IP \fBproto\fP \w'boottimeXX'u
- XA summary of various network protocol information is returned.
- XThis is the output from
- X.BR "netstat -s" .
- XUsually,
- Xthis statistic is too long to fit into a datagram.
- X.IP \fBtables\fP \w'boottimeXX'u
- XA summary of the utilization of various internal system tables.
- XThis is the output from
- X.BR "pstat -T" .
- X.IP \fBtime\fP \w'boottimeXX'u
- XThe current time is returned.
- X.IP \fBuptime\fP \w'boottimeXX'u
- XThe amount of time the system has been up is returned.
- X.IP \fBusers\fP \w'boottimeXX'u
- XThe number of users logged in is returned.
- X.IP \fBwho\fP \w'boottimeXX'u
- XA list of all logged in users.
- XThis list is contained on a single line,
- Xwith login names separated from each other by a space character.
- XOccasionally the output from this statistic will be too long to fit
- Xinto a datagram.
- X.SH SEE ALSO
- X.BR netstat (1),
- X.BR stats (1)
- X.br
- X\s-1RFC996\s0,
- X.IR "Statistics Server" ,
- XD. L. Mills,
- XFebruary 1987
- X.SH AUTHOR
- XDavid A. Curry,
- XPurdue University Engineering Computer Network
- ________This_Is_The_END________
- echo 'x - stats.h'
- sed 's/^X//' <<'________This_Is_The_END________' >>stats.h
- X/*
- X * $Header: /ecn1/src/ecn/statsrv/RCS/stats.h,v 1.1 87/10/17 21:01:03 davy Exp Locker: davy $
- X *
- X * stats.h - definitions for statistics server
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * davy@intrepid.ecn.purdue.edu
- X * October, 1987
- X *
- X * $Log: stats.h,v $
- X * Revision 1.1 87/10/17 21:01:03 davy
- X * Initial revision
- X *
- X */
- X
- X#define SERVNAME "statsrv" /* name of our service */
- X#define MAXDGRAM 576 /* maximum size of a datagram */
- X
- X#define KMEM "/dev/kmem" /* path to kernel memory */
- X
- X#if vax || sun || gould || tahoe
- X#define VMUNIX "/vmunix" /* path to kernel */
- X#endif
- X#if sequent
- X#define VMUNIX "/dynix"
- X#endif
- X
- X/*
- X * For 4.2BSD syslogs.
- X */
- X#ifndef LOG_DAEMON
- X#define LOG_DAEMON (3<<3)
- X#endif
- X
- Xextern int st_send(), st_recv(); /* stream send/recv functions */
- Xextern int dg_send(), dg_recv(); /* datagram send/recv functions */
- ________This_Is_The_END________
- echo 'x - dg_sendrecv.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>dg_sendrecv.c
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /ecn1/src/ecn/statsrv/RCS/dg_sendrecv.c,v 1.1 87/10/17 21:01:12 davy Exp $";
- X#endif
- X/*
- X * dg_sendrecv.c - datagram send/recv functions
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * davy@intrepid.ecn.purdue.edu
- X * October, 1987
- X *
- X * $Log: dg_sendrecv.c,v $
- X * Revision 1.1 87/10/17 21:01:12 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <syslog.h>
- X#include <stdio.h>
- X
- X#include "stats.h"
- X
- Xextern char *pname; /* program name */
- Xextern short server; /* 1 if server, 0 if client */
- Xextern struct sockaddr_in sin; /* address of remote host */
- X
- X/*
- X * dg_send - send buf as a datagram to the address in sin~r on socket s.
- X */
- Xdg_send(s, buf)
- Xchar *buf;
- Xint s;
- X{
- X register int cnt;
- X
- X /*
- X * We want the length including the null.
- X */
- X cnt = strlen(buf) + 1;
- X
- X /*
- X * According to RFC996, can be no larger than MAXDGRAM.
- X */
- X if (cnt > MAXDGRAM) {
- X if (server) {
- X strcpy(buf, "output length too long for datagram.\n");
- X cnt = strlen(buf) + 1;
- X }
- X else {
- X fprintf(stderr, "%s: string too long for datagram.\n", pname);
- X exit(1);
- X }
- X }
- X
- X /*
- X * Send the datagram.
- X */
- X if (sendto(s, buf, cnt, 0, &sin, sizeof(struct sockaddr_in)) < 0) {
- X if (server)
- X syslog(LOG_ERR, "sendto: %m");
- X else
- X error("sendto");
- X exit(1);
- X }
- X}
- X
- X/*
- X * dg_recv - receive a datagram of maximum size cnt into buf from the address
- X * in sin on socket s.
- X */
- Xdg_recv(s, buf, cnt)
- Xint s, cnt;
- Xchar *buf;
- X{
- X int len;
- X
- X len = sizeof(struct sockaddr_in);
- X
- X /*
- X * Receive the datagram.
- X */
- X if (recvfrom(s, buf, cnt, 0, &sin, &len) < 0) {
- X if (server)
- X syslog(LOG_ERR, "recvfrom: %m");
- X else
- X error("recvfrom");
- X exit(1);
- X }
- X}
- ________This_Is_The_END________
- echo 'x - getcpustats.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>getcpustats.c
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /ecn1/src/ecn/statsrv/RCS/getcpustats.c,v 1.2 87/10/29 14:24:02 davy Exp $";
- X#endif
- X/*
- X * getcpustats - get cpu usage statistics
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * davy@intrepid.ecn.purdue.edu
- X * October, 1987
- X *
- X * $Log: getcpustats.c,v $
- X * Revision 1.2 87/10/29 14:24:02 davy
- X * Modified to use VMUNIX and KMEM instead of hard-coded paths.
- X *
- X * Revision 1.1 87/10/17 21:01:18 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/file.h>
- X#include <sys/dk.h>
- X#include <syslog.h>
- X#include <nlist.h>
- X#include <stdio.h>
- X#include "stats.h"
- X
- Xstatic struct nlist nl[] = {
- X#define X_CPTIME 0
- X { "_cp_time" },
- X { 0 }
- X};
- X
- Xextern int (*fn_recv)(), (*fn_send)(); /* send/recv functions */
- X
- X/*
- X * getcpustats - get cpu usage statistics
- X */
- Xgetcpustats(name)
- Xchar *name;
- X{
- X int kmem;
- X double f;
- X register int i;
- X double percent();
- X char buf[BUFSIZ];
- X int user, nice, sys, idle;
- X long times1[CPUSTATES], times2[CPUSTATES];
- X
- X /*
- X * Open kernel memory.
- X */
- X if ((kmem = open(KMEM, O_RDONLY)) < 0) {
- X syslog(LOG_ERR, "open: %s: %m", KMEM);
- X exit(1);
- X }
- X
- X /*
- X * Read kernel namelist.
- X */
- X if ((nlist(VMUNIX, nl) < 0) || (nl[0].n_type == 0)) {
- X syslog(LOG_ERR, "%s: no namelist", VMUNIX);
- X exit(1);
- X }
- X
- X /*
- X * Read the first set of usage stats.
- X */
- X lseek(kmem, (long) nl[X_CPTIME].n_value, L_SET);
- X read(kmem, (char *) times1, sizeof(times1));
- X
- X /*
- X * Give it a time interval.
- X */
- X sleep(1);
- X
- X /*
- X * Read the second set of usage stats.
- X */
- X lseek(kmem, (long) nl[X_CPTIME].n_value, L_SET);
- X read(kmem, (char *) times2, sizeof(times2));
- X
- X /*
- X * Calculate change.
- X */
- X for (i=0; i < CPUSTATES; i++)
- X times2[i] -= times1[i];
- X
- X /*
- X * Calculate times.
- X */
- X for (i=0; i < CPUSTATES; i++) {
- X f = percent(i, times2);
- X
- X /*
- X * Save results. This is risky, and assumes the order
- X * is as given. Check sys/dk.h if you think it's wrong
- X * on your system.
- X */
- X switch (i) {
- X case 0:
- X user = (int) f;
- X break;
- X case 1:
- X nice = (int) f;
- X break;
- X case 2:
- X sys = (int) f;
- X break;
- X case 3:
- X idle = (int) f;
- X break;
- X }
- X }
- X
- X sprintf(buf, "user %d%% nice %d%% sys %d%% idle %d%%\n", user, nice, sys, idle);
- X (*fn_send)(0, buf);
- X close(kmem);
- X}
- X
- X/*
- X * percent - figure what percentage of time is used by row.
- X */
- Xstatic double percent(row, times)
- Xlong *times;
- Xint row;
- X{
- X double t;
- X register int i;
- X
- X t = 0.0;
- X for (i=0; i < CPUSTATES; i++)
- X t += times[i];
- X
- X if (t == 0.0)
- X t = 1.0;
- X
- X return(times[row] * 100.0 / t);
- X}
- ________This_Is_The_END________
- echo 'x - getloadstats.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>getloadstats.c
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /ecn1/src/ecn/statsrv/RCS/getloadstats.c,v 1.2 87/10/29 14:24:54 davy Exp $";
- X#endif
- X/*
- X * getloadstats - get load average statistics
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * davy@intrepid.ecn.purdue.edu
- X * October, 1987
- X *
- X * $Log: getloadstats.c,v $
- X * Revision 1.2 87/10/29 14:24:54 davy
- X * Modified to use VMUNIX and KMEM instead of hard-coded paths.
- X *
- X * Revision 1.1 87/10/17 21:01:23 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/file.h>
- X#include <syslog.h>
- X#include <nlist.h>
- X#include <stdio.h>
- X#include "stats.h"
- X
- Xstatic struct nlist nl[] = {
- X#define X_AVENRUN 0
- X { "_avenrun" },
- X { 0 }
- X};
- X
- Xextern int (*fn_recv)(), (*fn_send)(); /* send/recv functions */
- X
- X/*
- X * getloadstats - get load average statistics
- X */
- Xgetloadstats(name)
- Xchar *name;
- X{
- X int kmem;
- X char buf[BUFSIZ];
- X#ifdef sun
- X long avenrun[3];
- X#else
- X double avenrun[3];
- X#endif
- X
- X /*
- X * Open kernel memory.
- X */
- X if ((kmem = open(KMEM, O_RDONLY)) < 0) {
- X syslog(LOG_ERR, "open: %s: %m", KMEM);
- X exit(1);
- X }
- X
- X /*
- X * Read kernel namelist.
- X */
- X if ((nlist(VMUNIX, nl) < 0) || (nl[0].n_type == 0)) {
- X syslog(LOG_ERR, "%s: no namelist", VMUNIX);
- X exit(1);
- X }
- X
- X /*
- X * Read the load averages.
- X */
- X lseek(kmem, (long) nl[X_AVENRUN].n_value, L_SET);
- X read(kmem, (char *) avenrun, sizeof(avenrun));
- X
- X /*
- X * Return the one-minute load average.
- X */
- X#ifdef sun
- X sprintf(buf, "%.2f\n", (double) avenrun[0] / FSCALE);
- X#else
- X sprintf(buf, "%.2f\n", avenrun[0]);
- X#endif
- X
- X (*fn_send)(0, buf);
- X close(kmem);
- X}
- ________This_Is_The_END________
- echo 'x - getnetstats.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>getnetstats.c
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /ecn1/src/ecn/statsrv/RCS/getnetstats.c,v 1.1 87/10/17 21:01:29 davy Exp $";
- X#endif
- X/*
- X * getnetstats - get network statistics
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * davy@intrepid.ecn.purdue.edu
- X * October, 1987
- X *
- X * $Log: getnetstats.c,v $
- X * Revision 1.1 87/10/17 21:01:29 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <syslog.h>
- X#include <stdio.h>
- X
- X#define NETSTAT "/usr/ucb/netstat"
- X
- Xextern int (*fn_recv)(), (*fn_send)(); /* send/recv functions */
- X
- X/*
- X * getnetstats - get network statistic
- X */
- Xgetnetstats(name)
- Xchar *name;
- X{
- X int pid;
- X int pf[2];
- X char *flag;
- X register int cnt;
- X char buf[10 * BUFSIZ];
- X register char *s, *ebuf;
- X
- X /*
- X * Different stats get different flags.
- X */
- X if (!strcmp(name, "mbufs"))
- X flag = "-m";
- X else if (!strcmp(name, "packets"))
- X flag = "-i";
- X else if (!strcmp(name, "proto"))
- X flag = "-s";
- X
- X if (pipe(pf) < 0) {
- X syslog(LOG_ERR, "pipe: %m");
- X exit(1);
- X }
- X
- X /*
- X * Start a child.
- X */
- X if ((pid = vfork()) < 0) {
- X syslog(LOG_ERR, "fork: %m");
- X exit(1);
- X }
- X
- X /*
- X * Run the command.
- X */
- X if (pid == 0) {
- X close(pf[0]);
- X
- X dup2(pf[1], 1);
- X close(pf[1]);
- X
- X execl(NETSTAT, "netstat", flag, 0);
- X syslog(LOG_ERR, "exec: %m");
- X exit(1);
- X }
- X
- X close(pf[1]);
- X
- X /*
- X * Read from the pipe.
- X */
- X s = buf;
- X ebuf = &buf[sizeof(buf) - 1];
- X while ((cnt = read(pf[0], s, (int) (ebuf - s))) > 0) {
- X s += cnt;
- X
- X if (s > ebuf) {
- X syslog(LOG_ERR, "output from %s %s too big", NETSTAT, flag);
- X s = ebuf;
- X break;
- X }
- X }
- X
- X *s = '\0';
- X (*fn_send)(0, buf);
- X
- X close(pf[0]);
- X
- X /*
- X * Pick up the child.
- X */
- X while (wait((int *) 0) >= 0)
- X ;
- X}
- ________This_Is_The_END________
- echo 'x - gettablestats.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>gettablestats.c
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /ecn1/src/ecn/statsrv/RCS/gettablestats.c,v 1.1 87/12/08 14:40:03 davy Exp $";
- X#endif
- X/*
- X * gettablestats - get internal table statistics
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * davy@intrepid.ecn.purdue.edu
- X * December, 1987
- X *
- X * $Log: gettablestats.c,v $
- X * Revision 1.1 87/12/08 14:40:03 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <syslog.h>
- X#include <stdio.h>
- X
- X#define PSTAT "/etc/pstat"
- X
- Xextern int (*fn_recv)(), (*fn_send)(); /* send/recv functions */
- X
- X/*
- X * gettablestats - get internal table statistics
- X */
- Xgettablestats(name)
- Xchar *name;
- X{
- X int pid;
- X int pf[2];
- X char *flag;
- X register int cnt;
- X char buf[10 * BUFSIZ];
- X register char *s, *ebuf;
- X
- X /*
- X * Different stats get different flags.
- X */
- X if (!strcmp(name, "tables"))
- X flag = "-T";
- X
- X if (pipe(pf) < 0) {
- X syslog(LOG_ERR, "pipe: %m");
- X exit(1);
- X }
- X
- X /*
- X * Start a child.
- X */
- X if ((pid = vfork()) < 0) {
- X syslog(LOG_ERR, "fork: %m");
- X exit(1);
- X }
- X
- X /*
- X * Run the command.
- X */
- X if (pid == 0) {
- X close(pf[0]);
- X
- X dup2(pf[1], 1);
- X close(pf[1]);
- X
- X execl(PSTAT, "pstat", flag, 0);
- X syslog(LOG_ERR, "exec: %m");
- X exit(1);
- X }
- X
- X close(pf[1]);
- X
- X /*
- X * Read from the pipe.
- X */
- X s = buf;
- X ebuf = &buf[sizeof(buf) - 1];
- X while ((cnt = read(pf[0], s, (int) (ebuf - s))) > 0) {
- X s += cnt;
- X
- X if (s > ebuf) {
- X syslog(LOG_ERR, "output from %s %s too big", PSTAT, flag);
- X s = ebuf;
- X break;
- X }
- X }
- X
- X *s = '\0';
- X (*fn_send)(0, buf);
- X
- X close(pf[0]);
- X
- X /*
- X * Pick up the child.
- X */
- X while (wait((int *) 0) >= 0)
- X ;
- X}
- ________This_Is_The_END________
- echo 'x - gettimestats.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>gettimestats.c
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /ecn1/src/ecn/statsrv/RCS/gettimestats.c,v 1.3 87/10/29 15:03:57 davy Exp $";
- X#endif
- X/*
- X * gettimestats - get time-related statistics
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * davy@intrepid.ecn.purdue.edu
- X * October, 1987
- X *
- X * $Log: gettimestats.c,v $
- X * Revision 1.3 87/10/29 15:03:57 davy
- X * Fixed bug with timezone printing.
- X *
- X * Revision 1.2 87/10/29 14:25:03 davy
- X * Modified to use VMUNIX and KMEM instead of hard-coded paths.
- X *
- X * Revision 1.1 87/10/17 21:01:34 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/file.h>
- X#include <sys/time.h>
- X#include <syslog.h>
- X#include <nlist.h>
- X#include <stdio.h>
- X#include "stats.h"
- X
- Xstatic struct nlist nl[] = {
- X#define X_BOOTTIME 0
- X { "_boottime" },
- X { 0 }
- X};
- X
- Xextern int (*fn_recv)(), (*fn_send)(); /* send/recv functions */
- X
- X/*
- X * gettimestats - get time-related statistics
- X */
- Xgettimestats(name)
- Xchar *name;
- X{
- X int kmem;
- X struct timezone tz;
- X struct timeval curtime, boottime;
- X
- X /*
- X * Get current date and time.
- X */
- X gettimeofday(&curtime, &tz);
- X
- X /*
- X * If we're doing "date" or "time", we just print
- X * out the current date and time.
- X */
- X if (!strcmp(name, "date") || !strcmp(name, "time")) {
- X prdate(&curtime, &tz);
- X return;
- X }
- X
- X /*
- X * Open kernel memory.
- X */
- X if ((kmem = open(KMEM, O_RDONLY)) < 0) {
- X syslog(LOG_ERR, "open: %s: %m", KMEM);
- X exit(1);
- X }
- X
- X /*
- X * Read kernel namelist.
- X */
- X if ((nlist(VMUNIX, nl) < 0) || (nl[0].n_type == 0)) {
- X syslog(LOG_ERR, "%s: no namelist", VMUNIX);
- X exit(1);
- X }
- X
- X /*
- X * Read the boot time.
- X */
- X lseek(kmem, (long) nl[X_BOOTTIME].n_value, L_SET);
- X read(kmem, (char *) &boottime, sizeof(boottime));
- X
- X /*
- X * For "boottime" we just print the boot time, for
- X * "uptime" we print the time up.
- X */
- X if (!strcmp(name, "boottime")) {
- X prdate(&boottime, &tz);
- X }
- X else {
- X curtime.tv_sec -= boottime.tv_sec;
- X prtime(&curtime);
- X }
- X
- X close(kmem);
- X}
- X
- X/*
- X * prdate - print date and time
- X */
- Xstatic prdate(tv, tz)
- Xstruct timezone *tz;
- Xstruct timeval *tv;
- X{
- X char buf[64];
- X struct tm *tm;
- X struct tm *localtime();
- X register char *ap, *tzn;
- X char *asctime(), *timezone();
- X
- X tm = localtime(&tv->tv_sec);
- X
- X ap = asctime(tm);
- X tzn = timezone(tz->tz_minuteswest, tm->tm_isdst);
- X
- X /*
- X * Date and time.
- X */
- X strncpy(buf, ap, 20);
- X buf[20] = '\0';
- X
- X /*
- X * Timezone.
- X */
- X if (tzn)
- X strcat(buf, tzn);
- X
- X /*
- X * Year.
- X */
- X strcat(buf, ap+19);
- X
- X (*fn_send)(0, buf);
- X}
- X
- X/*
- X * prtime - print time as days, hours, minutes, seconds.
- X */
- Xstatic prtime(tv)
- Xstruct timeval *tv;
- X{
- X char tmp[32], buf[128];
- X
- X *buf = '\0';
- X
- X if (tv->tv_sec >= 86400) {
- X sprintf(tmp, "%d days ", tv->tv_sec / 86400);
- X tv->tv_sec %= 86400;
- X strcat(buf, tmp);
- X }
- X
- X if (tv->tv_sec >= 3600) {
- X sprintf(tmp, "%d hours ", tv->tv_sec / 3600);
- X tv->tv_sec %= 3600;
- X strcat(buf, tmp);
- X }
- X
- X if (tv->tv_sec >= 60) {
- X sprintf(tmp, "%d minutes ", tv->tv_sec / 60);
- X tv->tv_sec %= 60;
- X strcat(buf, tmp);
- X }
- X
- X if (tv->tv_sec) {
- X sprintf(tmp, "%d seconds", tv->tv_sec);
- X strcat(buf, tmp);
- X }
- X
- X strcat(buf, "\n");
- X (*fn_send)(0, buf);
- X}
- ________This_Is_The_END________
- echo 'x - getuserstats.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>getuserstats.c
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /ecn1/src/ecn/statsrv/RCS/getuserstats.c,v 1.3 87/12/08 14:39:06 davy Exp $";
- X#endif
- X/*
- X * getuserstats - get user statistics
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * davy@intrepid.ecn.purdue.edu
- X * October, 1987
- X *
- X * $Log: getuserstats.c,v $
- X * Revision 1.3 87/12/08 14:39:06 davy
- X * Added code for the "who" statistic.
- X *
- X * Revision 1.2 87/10/29 14:24:36 davy
- X * Modified to use UTMP instead of hard-coded path.
- X *
- X * Revision 1.1 87/10/17 21:01:40 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/stat.h>
- X#include <sys/time.h>
- X#include <syslog.h>
- X#include <stdio.h>
- X#include <utmp.h>
- X
- X#define WHO 0
- X#define USERS 1
- X#define ACTUSERS 2
- X
- X#define UTMP "/etc/utmp"
- X#define USERBUFSIZE 2048 /* 256 8-char logins */
- X
- Xextern int (*fn_recv)(), (*fn_send)(); /* send/recv functions */
- X
- X/*
- X * getuserstats - get user statistics
- X */
- Xgetuserstats(name)
- Xchar *name;
- X{
- X FILE *fp;
- X char buf[32];
- X struct utmp ut;
- X struct stat st;
- X struct timeval tv;
- X register int cnt, mode;
- X char userbuf[USERBUFSIZE];
- X
- X /*
- X * "actusers" means we only want active users.
- X * "who" means we want user names.
- X */
- X if (!strcmp(name, "actusers"))
- X mode = ACTUSERS;
- X else if (!strcmp(name, "users"))
- X mode = USERS;
- X else
- X mode = WHO;
- X
- X if ((fp = fopen(UTMP, "r")) == NULL) {
- X syslog(LOG_ERR, "cannot open %s", UTMP);
- X exit(1);
- X }
- X
- X *userbuf = NULL;
- X gettimeofday(&tv, (struct timeval *) 0);
- X
- X /*
- X * For each user...
- X */
- X cnt = 0;
- X while (fread(&ut, sizeof(struct utmp), 1, fp) == 1) {
- X /*
- X * Not logged in.
- X */
- X if (ut.ut_name[0] == NULL)
- X continue;
- X
- X /*
- X * For active users, see how long he's been idle.
- X */
- X if (mode == ACTUSERS) {
- X sprintf(buf, "/dev/%.8s", ut.ut_line);
- X
- X if (stat(buf, &st) < 0)
- X continue;
- X
- X /*
- X * If idle less than 1 hour, he's active.
- X */
- X if ((tv.tv_sec - st.st_atime) < 3600)
- X cnt++;
- X }
- X else {
- X /*
- X * Copy the login name if needed.
- X */
- X if (mode == WHO) {
- X sprintf(buf, "%.8s ", ut.ut_name);
- X strcat(userbuf, buf);
- X }
- X
- X cnt++;
- X }
- X }
- X
- X /*
- X * Send the appropriate buffer.
- X */
- X if (mode == WHO) {
- X strcat(userbuf, "\n");
- X (*fn_send)(0, userbuf);
- X }
- X else {
- X sprintf(buf, "%d\n", cnt);
- X (*fn_send)(0, buf);
- X }
- X
- X fclose(fp);
- X}
- ________This_Is_The_END________
- echo 'x - st_sendrecv.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>st_sendrecv.c
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /ecn1/src/ecn/statsrv/RCS/st_sendrecv.c,v 1.2 87/10/19 08:37:02 davy Exp $";
- X#endif
- X/*
- X * st_sendrecv.c - stream send/recv functions
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * davy@intrepid.ecn.purdue.edu
- X * October, 1987
- X *
- X * $Log: st_sendrecv.c,v $
- X * Revision 1.2 87/10/19 08:37:02 davy
- X * Fixed to catch end of file on socket.
- X *
- X * Revision 1.1 87/10/17 21:01:46 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <syslog.h>
- X#include <stdio.h>
- X
- X#include "stats.h"
- X
- Xextern char *pname;
- Xextern short server;
- X
- X/*
- X * st_send - send buf on the socket s.
- X */
- Xst_send(s, buf)
- Xchar *buf;
- Xint s;
- X{
- X register int cnt;
- X
- X /*
- X * We want the length including the null.
- X */
- X cnt = strlen(buf) + 1;
- X
- X /*
- X * Send the buffer.
- X */
- X if (send(s, buf, cnt, 0) < 0) {
- X if (server)
- X syslog(LOG_ERR, "send: %m");
- X else
- X error("send");
- X exit(1);
- X }
- X}
- X
- X/*
- X * st_recv - receive data of maximum length cnt into the buffer buf on
- X * socket s. err describes what we're expecting for the error
- X * message.
- X */
- Xst_recv(s, buf, cnt, err)
- Xchar *buf, *err;
- Xint s, cnt;
- X{
- X char c;
- X register int n;
- X
- X /*
- X * Receive a character at a time up to a null.
- X */
- X do {
- X if ((n = recv(s, &c, sizeof(char), 0)) < 0) {
- X if (server)
- X syslog(LOG_ERR, "recv: %m");
- X else
- X error("recv");
- X exit(1);
- X }
- X
- X /*
- X * End of file.
- X */
- X if (n == 0)
- X exit(0);
- X
- X if (--cnt < 0) {
- X if (server)
- X syslog(LOG_ERR, "%s too long", err);
- X else
- X fprintf(stderr, "%s: %s too long.\n", pname, err);
- X exit(1);
- X }
- X
- X *buf++ = c;
- X } while (c != '\0');
- X}
- ________This_Is_The_END________
- echo 'x - stats.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>stats.c
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /ecn1/src/ecn/statsrv/RCS/stats.c,v 1.1 87/10/17 21:01:52 davy Exp $";
- X#endif
- X/*
- X * stats - retrieve statistics from the statistics server
- X *
- X * Usage: stats [-d] host statname [statname...]
- X *
- X * The STATSRV protocol is described in RFC996, "Statistics Server",
- X * D.L. Mills, February 1987.
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * davy@intrepid.ecn.purdue.edu
- X * October, 1987
- X *
- X * $Log: stats.c,v $
- X * Revision 1.1 87/10/17 21:01:52 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <netdb.h>
- X#include <stdio.h>
- X
- X#include "stats.h"
- X
- Xchar *pname; /* program name */
- Xshort server = 0; /* indicates we aren't server */
- Xstruct sockaddr_in sin; /* address of remote host */
- Xint (*fn_send)(), (*fn_recv)(); /* send/recv functions */
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X int socktype;
- X register int s;
- X char buf[10240];
- X struct hostent *hp;
- X struct servent *sp;
- X char *host, *servtype;
- X struct hostent *gethostbyname();
- X struct servent *getservbyname();
- X
- X pname = *argv;
- X
- X /*
- X * Set up to use TCP stream sockets.
- X */
- X servtype = "tcp";
- X fn_recv = st_recv;
- X fn_send = st_send;
- X socktype = SOCK_STREAM;
- X
- X /*
- X * Check arguments.
- X */
- Xargchk: if (argc < 3) {
- X fprintf(stderr, "Usage: %s [-d] host statname [statname...]\n", pname);
- X fprintf(stderr, " use the \"help\" statistic for more info.\n");
- X exit(1);
- X }
- X
- X /*
- X * -d indicates use datagrams; set up to use
- X * datagram sockets and then go recheck the
- X * argument list.
- X */
- X if (!strcmp(*++argv, "-d")) {
- X socktype = SOCK_DGRAM;
- X fn_recv = dg_recv;
- X fn_send = dg_send;
- X servtype = "udp";
- X argc--;
- X
- X goto argchk;
- X }
- X
- X /*
- X * Host is first argument.
- X */
- X argc--;
- X host = *argv;
- X
- X /*
- X * Get a socket.
- X */
- X if ((s = socket(AF_INET, socktype, 0)) < 0) {
- X error("socket");
- X exit(1);
- X }
- X
- X /*
- X * Look up the host's address.
- X */
- X if ((hp = gethostbyname(host)) == NULL) {
- X fprintf(stderr, "%s: %s: host unknown.\n", pname, host);
- X exit(1);
- X }
- X
- X /*
- X * Look up the port the server lives on.
- X */
- X if ((sp = getservbyname(SERVNAME, servtype)) == NULL) {
- X fprintf(stderr, "%s: %s/%s: service unknown.\n", pname, SERVNAME, servtype);
- X exit(1);
- X }
- X
- X /*
- X * Build the server's address.
- X */
- X sin.sin_port = sp->s_port;
- X sin.sin_family = hp->h_addrtype;
- X bcopy(hp->h_addr, &sin.sin_addr, sizeof(sin.sin_addr));
- X
- X /*
- X * If we're using a stream socket, connect to
- X * the remote host.
- X */
- X if (socktype == SOCK_STREAM) {
- X if (connect(s, &sin, sizeof(struct sockaddr_in)) < 0) {
- X error("connect");
- X exit(1);
- X }
- X }
- X
- X /*
- X * For each statistic requested...
- X */
- X while (--argc) {
- X /*
- X * Send the name of the statistic to the
- X * server.
- X */
- X (*fn_send)(s, *++argv);
- X
- X /*
- X * Wait for a response.
- X */
- X (*fn_recv)(s, buf, sizeof(buf), "response");
- X
- X /*
- X * Print what we got.
- X */
- X fputs(buf, stdout);
- X }
- X
- X exit(0);
- X}
- X
- X/*
- X * error - print program name and error message.
- X */
- Xerror(s)
- X{
- X fprintf(stderr, "%s: ", pname);
- X perror(s);
- X}
- ________This_Is_The_END________
- echo 'x - statsrv.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>statsrv.c
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /ecn1/src/ecn/statsrv/RCS/statsrv.c,v 1.2 87/12/08 14:39:23 davy Exp $";
- X#endif
- X/*
- X * statsrv - statistics server
- X *
- X * Statsrv is invoked via inetd(8). Place the following lines in your
- X * inetd.conf file (statsrv is port 133 for both udp and tcp):
- X *
- X * statsrv stream tcp nowait root /etc/statsrv statsrv
- X * statsrv dgram udp wait root /etc/statsrv statsrv
- X *
- X * The STATSRV protocol is described in RFC996, "Statistics Server",
- X * D.L. Mills, February 1987.
- X *
- X * David A. Curry
- X * Purdue University
- X * Engineering Computer Network
- X * davy@intrepid.ecn.purdue.edu
- X * October, 1987
- X *
- X * $Log: statsrv.c,v $
- X * Revision 1.2 87/12/08 14:39:23 davy
- X * Added lines for the "tables" and "who" commands.
- X *
- X * Revision 1.1 87/10/17 21:01:57 davy
- X * Initial revision
- X *
- X */
- X#include <sys/param.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <syslog.h>
- X#include <errno.h>
- X#include <ctype.h>
- X#include <stdio.h>
- X
- X#include "stats.h"
- X
- X/*
- X * One of these for each statistic we understand.
- X */
- Xstruct statistic {
- X char *st_name;
- X int (*st_func)();
- X};
- X
- X/*
- X * Functions which do the statistics.
- X */
- Xextern int liststats();
- Xextern int getcpustats();
- Xextern int getnetstats();
- Xextern int getloadstats();
- Xextern int getuserstats();
- Xextern int gettimestats();
- Xextern int gettablestats();
- X
- X/*
- X * Statistics we understand.
- X */
- Xstatic struct statistic stats[] = {
- X { "actusers", getuserstats },
- X { "boottime", gettimestats },
- X { "cpu", getcpustats },
- X { "date", gettimestats },
- X { "help", liststats },
- X { "loadav", getloadstats },
- X { "mbufs", getnetstats },
- X { "packets", getnetstats },
- X { "proto", getnetstats },
- X { "tables", gettablestats },
- X { "time", gettimestats },
- X { "uptime", gettimestats },
- X { "users", getuserstats },
- X { "who", getuserstats },
- X { 0, 0 }
- X};
- X
- Xchar *pname; /* program name */
- Xshort server = 1; /* indicates we're the server */
- Xstruct sockaddr_in sin; /* address of remote host */
- Xint (*fn_recv)(), (*fn_send)(); /* send/recv functions */
- X
- Xextern int errno;
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X char *rindex();
- X char buf[BUFSIZ];
- X register char *s;
- X int len, socktype;
- X register struct statistic *st;
- X
- X /*
- X * Get program name.
- X */
- X if ((pname = rindex(*argv, '/')) == NULL)
- X pname = *argv;
- X else
- X pname++;
- X
- X /*
- X * Set up syslog.
- X */
- X openlog(pname, LOG_PID, LOG_DAEMON);
- X
- X /*
- X * Set up to run on stream sockets.
- X */
- X fn_recv = st_recv;
- X fn_send = st_send;
- X socktype = SOCK_STREAM;
- X
- X /*
- X * Figure out if we're on a stream or datagram socket. If
- X * we are on a datagram socket, we have no peer, and we
- X * will get an ENOTCONN error.
- X */
- X len = sizeof(struct sockaddr_in);
- X if (getpeername(0, &sin, &len) < 0) {
- X /*
- X * Datagram socket.
- X */
- X if (errno == ENOTCONN) {
- X socktype = SOCK_DGRAM;
- X fn_recv = dg_recv;
- X fn_send = dg_send;
- X }
- X else {
- X syslog(LOG_ERR, "getpeername: %m");
- X exit(1);
- X }
- X }
- X
- X /*
- X * Forever...
- X */
- Xtop: for (;;) {
- X /*
- X * Get a statistic request from the remote host.
- X */
- X (*fn_recv)(0, buf, sizeof(buf), "statname");
- X
- X /*
- X * Convert to lower case.
- X */
- X for (s = buf; *s; s++) {
- X if (isupper(*s))
- X *s = tolower(*s);
- X }
- X
- X /*
- X * Look up the statistic and run the
- X * function.
- X */
- X for (st = stats; st->st_name; st++) {
- X if (!strcmp(st->st_name, buf)) {
- X (*(st->st_func))(buf);
- X
- X /*
- X * Only one statistic per datagram.
- X */
- X if (socktype == SOCK_DGRAM)
- X exit(0);
- X
- X goto top;
- X }
- X }
- X
- X /*
- X * Unknown statistic.
- X */
- X (*fn_send)(0, "unknown command - use \"help\" for list.\n");
- X exit(1);
- X }
- X}
- X
- X/*
- X * liststats - list statistics we know about.
- X */
- Xliststats(name)
- Xchar *name;
- X{
- X char buf[BUFSIZ];
- X register struct statistic *st;
- X
- X *buf = '\0';
- X
- X for (st = stats; st->st_name; st++) {
- X strcat(buf, st->st_name);
- X strcat(buf, "\n");
- X }
- X
- X (*fn_send)(0, buf);
- X}
- X
- X/*
- X * error - print program name and error message.
- X */
- Xerror(s)
- X{
- X fprintf(stderr, "%s: ", pname);
- X perror(s);
- X}
- ________This_Is_The_END________
- echo 'x - tester'
- sed 's/^X//' <<'________This_Is_The_END________' >>tester
- X#!/bin/csh -f
- X
- Xset hostname = `hostname`
- X
- Xforeach i (actusers boottime cpu date help loadav mbufs packets proto \
- X tables time uptime users who)
- X echo "--------- $i (stream) ---------"
- X stats $hostname $i
- X echo "--------- $i (datagram) ---------"
- X stats -d $hostname $i
- Xend
- X
- ________This_Is_The_END________
- echo 'x - rfc'
- sed 's/^X//' <<'________This_Is_The_END________' >>rfc
- X
- XNetwork Working Group D.L. Mills
- XRequest for Comments: 996 University of Delaware
- X February 1987
- X
- X
- X Statistics Server
- X
- XSTATUS OF THIS MEMO
- X
- X This RFC specifies a standard for the ARPA Internet community. Hosts
- X and gateways on the DARPA Internet that choose to implement a remote
- X statistics monitoring facility may use this protocol to send
- X statistics data upon request to a monitoring center or debugging
- X host. Distribution of this memo is unlimited.
- X
- XDISCUSSION
- X
- X Many host and gateway implementations include a facility which
- X records traffic statistics, such as packet counters, error counters
- X and significant event counters for debugging and performance
- X evluation. Simple data-access and formatting programs can be used to
- X display these statistics along with the status of connections, etc.
- X Several operating systems, including the various Unix systems and
- X Fuzzball systems, already provide extensive facilities to capture and
- X display these data for local users and/or operators.
- X
- X In many instances it is highly useful to observe statistics data on
- X remote hosts and gateways from a monitoring center or debugging host.
- X Indeed, several protocols have been implemented and used expressly
- X for this purpose [1-6]. In many cases the data can be retrieved using
- X conventional services such as remote login or even file transfer.
- X However, use of these heavyweight mechanisms is awkward and intrusive
- X if conducted on a regular, frequent basis and may involve substantial
- X intrusion in the operating system if retrofitted to existing systems.
- X
- X The Statistics Server (STATSRV) protocol is intended as a lightweight
- X mechanism similar in spirit to NETSTAT [7] and complementary to it.
- X STATSRV is designed to capture statistics data with minimal intrusion
- X on existing systems or networks. It is intended for use with existing
- X hosts and gateways primarily for casual monitoring and debugging
- X purposes. It is not intended as a full-function monitoring protocol
- X [1,5,6] providing detailed, standardized reports suitable for machine
- X analysis, for example, but could be useful in exploratory development
- X leading to enduring systems of this type.
- X
- X The STATSRV model is based on the native host command language used
- X for statistics monitoring and display. The client sends a null-
- X terminated ASCII command to the server, which then responds with a
- X null-terminated ASCII response suitable for a printer or CRT display.
- X Although in principle STATSRV could be used over TCP, it is less
- X intrusive and more efficient to use it over UDP. In the case of UDP,
- X
- X
- X
- XD. L. Mills [Page 1]
- X
- XRFC 996 February 1987
- X
- X
- X commands and responses must fit into a single 576-octet IP datagram.
- X In both UDP and TCP the assigned port number is 133 (decimal).
- X
- X As is conventional in other lightweight services of this type
- X (NETSTAT, FINGER, etc.), there is no provision for access control or
- X authentication in STATSRV. If necessary, each command could include a
- X password or other mechanism to discourage casual abuse.
- X
- XEXAMPLE
- X
- X The Fuzzball system includes many local commands to display internal
- X data structures, including one that produces the following billboard
- X for each network device, in this case "dm0" on host "udel2.udel.edu":
- X
- X Process type: 000027 options: 040000
- X Subnet: DMV status: 376 hello: 15 timeout: 2000
- X Foreign address: [192.5.39.87] max size: 576
- X Input packets 3645 Output packets 3690
- X bad format 0 ICMP msgs 0
- X bad checksum 0 Input errors 0
- X returned 0 Output errors 0
- X dropped 2 No buffer 0
- X HELLO msgs 2286 Preempted 0
- X
- X The same billboard is returned as a null-terminated ASCII string in a
- X UDP datagram by sending the null-terminated ASCII command "dm0" in a
- X UDP datagram to the host. Similar billboards can be produced for most
- X processes in the system. Unix programs and shell scripts have been
- X built which send commands like these to selected hosts on a periodic
- X basis in order to construct a simple, ad-hoc monitoring facility.
- X
- XREFERENCES
- X
- X [1] Flood Page, D.,"Gateway Monitoring Protocol", DARPA Network
- X Working Group Report IEN-131, Bolt Beranek and Newman, February
- X 1980.
- X
- X [2] Flood Page, D., "The CMCC Terminal Process", DARPA Network
- X Working Group Report IEN-132, Bolt Beranek and Newman, February
- X 1980.
- X
- X [3] Flood Page, D., "CMCC Performance Measurement Message Formats",
- X DARPA Network Working Group Report IEN-157, Bolt Beranek and
- X Newman, September 1980.
- X
- X [4] Jones, R.G., " A Proposal for Simple Measurement Support for
- X Users", DARPA Network Working Group Report IEN-161, University
- X College London, November 1980.
- X
- X
- X
- X
- X
- X
- XD. L. Mills [Page 2]
- X
- XRFC 996 February 1987
- X
- X
- X [5] Littauer, B.M., A.J. Huang and R.M. Hinden," A Host Monitoring
- X Protocol", DARPA Network Working Group Report IEN-197, Bolt
- X Beranek and Newman, September 1981.
- X
- X [6] Hinden, R.M.," A Host Monitoring Protocol", DARPA Network
- X Working Group Report RFC-869, BBN Communications Corporation,
- X December 1983.
- X
- X [7] Reynolds, J.K., and J. Postel, "Assigned Numbers", DARPA Network
- X Working Group Report RFC-990, USC Information Sciences
- X Institute, November 1986.
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- XD. L. Mills [Page 3]
- X
- ________This_Is_The_END________
- exit
-
-